SGL
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.3
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.11.3
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.11.3
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
63 #warning "Already included a different version of the library!"
64 #endif
65 #endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
77 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
78#endif
79
80#if JSON_DIAGNOSTICS
81 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
82#else
83 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
84#endif
85
86#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
87 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
88#else
89 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
90#endif
91
92#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
93 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
94#endif
95
96// Construct the namespace ABI tags component
97#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
98#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
99 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
100
101#define NLOHMANN_JSON_ABI_TAGS \
102 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
103 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
104 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
105
106// Construct the namespace version component
107#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
108 _v ## major ## _ ## minor ## _ ## patch
109#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
110 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
111
112#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
113#define NLOHMANN_JSON_NAMESPACE_VERSION
114#else
115#define NLOHMANN_JSON_NAMESPACE_VERSION \
116 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
117 NLOHMANN_JSON_VERSION_MINOR, \
118 NLOHMANN_JSON_VERSION_PATCH)
119#endif
120
121// Combine namespace components
122#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
123#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
124 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
125
126#ifndef NLOHMANN_JSON_NAMESPACE
127#define NLOHMANN_JSON_NAMESPACE \
128 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
129 NLOHMANN_JSON_ABI_TAGS, \
130 NLOHMANN_JSON_NAMESPACE_VERSION)
131#endif
132
133#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
134#define NLOHMANN_JSON_NAMESPACE_BEGIN \
135 namespace nlohmann \
136 { \
137 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
138 NLOHMANN_JSON_ABI_TAGS, \
139 NLOHMANN_JSON_NAMESPACE_VERSION) \
140 {
141#endif
142
143#ifndef NLOHMANN_JSON_NAMESPACE_END
144#define NLOHMANN_JSON_NAMESPACE_END \
145 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
146 } // namespace nlohmann
147#endif
148
149// #include <nlohmann/detail/conversions/from_json.hpp>
150// __ _____ _____ _____
151// __| | __| | | | JSON for Modern C++
152// | | |__ | | | | | | version 3.11.3
153// |_____|_____|_____|_|___| https://github.com/nlohmann/json
154//
155// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
156// SPDX-License-Identifier: MIT
157
158
159
160#include <algorithm> // transform
161#include <array> // array
162#include <forward_list> // forward_list
163#include <iterator> // inserter, front_inserter, end
164#include <map> // map
165#ifdef JSON_HAS_CPP_17
166 #include <optional> // optional
167#endif
168#include <string> // string
169#include <tuple> // tuple, make_tuple
170#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
171#include <unordered_map> // unordered_map
172#include <utility> // pair, declval
173#include <valarray> // valarray
174
175
176// #include <nlohmann/detail/exceptions.hpp>
177// __ _____ _____ _____
178// __| | __| | | | JSON for Modern C++
179// | | |__ | | | | | | version 3.11.3
180// |_____|_____|_____|_|___| https://github.com/nlohmann/json
181//
182// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
183// SPDX-License-Identifier: MIT
184
185
186
187#include <cstddef> // nullptr_t
188#include <exception> // exception
189#if JSON_DIAGNOSTICS
190 #include <numeric> // accumulate
191#endif
192#include <stdexcept> // runtime_error
193#include <string> // to_string
194#include <vector> // vector
195
196// #include <nlohmann/detail/value_t.hpp>
197// __ _____ _____ _____
198// __| | __| | | | JSON for Modern C++
199// | | |__ | | | | | | version 3.11.3
200// |_____|_____|_____|_|___| https://github.com/nlohmann/json
201//
202// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
203// SPDX-License-Identifier: MIT
204
205
206
207#include <array> // array
208#include <cstddef> // size_t
209#include <cstdint> // uint8_t
210#include <string> // string
211
212// #include <nlohmann/detail/macro_scope.hpp>
213// __ _____ _____ _____
214// __| | __| | | | JSON for Modern C++
215// | | |__ | | | | | | version 3.11.3
216// |_____|_____|_____|_|___| https://github.com/nlohmann/json
217//
218// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
219// SPDX-License-Identifier: MIT
220
221
222
223#include <utility> // declval, pair
224// #include <nlohmann/detail/meta/detected.hpp>
225// __ _____ _____ _____
226// __| | __| | | | JSON for Modern C++
227// | | |__ | | | | | | version 3.11.3
228// |_____|_____|_____|_|___| https://github.com/nlohmann/json
229//
230// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
231// SPDX-License-Identifier: MIT
232
233
234
235#include <type_traits>
236
237// #include <nlohmann/detail/meta/void_t.hpp>
238// __ _____ _____ _____
239// __| | __| | | | JSON for Modern C++
240// | | |__ | | | | | | version 3.11.3
241// |_____|_____|_____|_|___| https://github.com/nlohmann/json
242//
243// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
244// SPDX-License-Identifier: MIT
245
246
247
248// #include <nlohmann/detail/abi_macros.hpp>
249
250
252namespace detail
253{
254
255template<typename ...Ts> struct make_void
256{
257 using type = void;
258};
259template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
260
261} // namespace detail
263
264
266namespace detail
267{
268
269// https://en.cppreference.com/w/cpp/experimental/is_detected
271{
272 nonesuch() = delete;
273 ~nonesuch() = delete;
274 nonesuch(nonesuch const&) = delete;
275 nonesuch(nonesuch const&&) = delete;
276 void operator=(nonesuch const&) = delete;
277 void operator=(nonesuch&&) = delete;
278};
279
280template<class Default,
281 class AlwaysVoid,
282 template<class...> class Op,
283 class... Args>
285{
286 using value_t = std::false_type;
287 using type = Default;
288};
289
290template<class Default, template<class...> class Op, class... Args>
291struct detector<Default, void_t<Op<Args...>>, Op, Args...>
292{
293 using value_t = std::true_type;
294 using type = Op<Args...>;
295};
296
297template<template<class...> class Op, class... Args>
298using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
299
300template<template<class...> class Op, class... Args>
301struct is_detected_lazy : is_detected<Op, Args...> { };
302
303template<template<class...> class Op, class... Args>
304using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
305
306template<class Default, template<class...> class Op, class... Args>
307using detected_or = detector<Default, void, Op, Args...>;
308
309template<class Default, template<class...> class Op, class... Args>
310using detected_or_t = typename detected_or<Default, Op, Args...>::type;
311
312template<class Expected, template<class...> class Op, class... Args>
313using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
314
315template<class To, template<class...> class Op, class... Args>
317 std::is_convertible<detected_t<Op, Args...>, To>;
318
319} // namespace detail
321
322// #include <nlohmann/thirdparty/hedley/hedley.hpp>
323
324
325// __ _____ _____ _____
326// __| | __| | | | JSON for Modern C++
327// | | |__ | | | | | | version 3.11.3
328// |_____|_____|_____|_|___| https://github.com/nlohmann/json
329//
330// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
331// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
332// SPDX-License-Identifier: MIT
333
334/* Hedley - https://nemequ.github.io/hedley
335 * Created by Evan Nemerson <evan@nemerson.com>
336 */
337
338#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
339#if defined(JSON_HEDLEY_VERSION)
340 #undef JSON_HEDLEY_VERSION
341#endif
342#define JSON_HEDLEY_VERSION 15
343
344#if defined(JSON_HEDLEY_STRINGIFY_EX)
345 #undef JSON_HEDLEY_STRINGIFY_EX
346#endif
347#define JSON_HEDLEY_STRINGIFY_EX(x) #x
348
349#if defined(JSON_HEDLEY_STRINGIFY)
350 #undef JSON_HEDLEY_STRINGIFY
351#endif
352#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
353
354#if defined(JSON_HEDLEY_CONCAT_EX)
355 #undef JSON_HEDLEY_CONCAT_EX
356#endif
357#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
358
359#if defined(JSON_HEDLEY_CONCAT)
360 #undef JSON_HEDLEY_CONCAT
361#endif
362#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
363
364#if defined(JSON_HEDLEY_CONCAT3_EX)
365 #undef JSON_HEDLEY_CONCAT3_EX
366#endif
367#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
368
369#if defined(JSON_HEDLEY_CONCAT3)
370 #undef JSON_HEDLEY_CONCAT3
371#endif
372#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
373
374#if defined(JSON_HEDLEY_VERSION_ENCODE)
375 #undef JSON_HEDLEY_VERSION_ENCODE
376#endif
377#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
378
379#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
380 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
381#endif
382#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
383
384#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
385 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
386#endif
387#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
388
389#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
390 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
391#endif
392#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
393
394#if defined(JSON_HEDLEY_GNUC_VERSION)
395 #undef JSON_HEDLEY_GNUC_VERSION
396#endif
397#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
398 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
399#elif defined(__GNUC__)
400 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
401#endif
402
403#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
404 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
405#endif
406#if defined(JSON_HEDLEY_GNUC_VERSION)
407 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
408#else
409 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
410#endif
411
412#if defined(JSON_HEDLEY_MSVC_VERSION)
413 #undef JSON_HEDLEY_MSVC_VERSION
414#endif
415#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
416 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
417#elif defined(_MSC_FULL_VER) && !defined(__ICL)
418 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
419#elif defined(_MSC_VER) && !defined(__ICL)
420 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
421#endif
422
423#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
424 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
425#endif
426#if !defined(JSON_HEDLEY_MSVC_VERSION)
427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
428#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
429 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
430#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
431 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
432#else
433 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
434#endif
435
436#if defined(JSON_HEDLEY_INTEL_VERSION)
437 #undef JSON_HEDLEY_INTEL_VERSION
438#endif
439#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
440 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
441#elif defined(__INTEL_COMPILER) && !defined(__ICL)
442 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
443#endif
444
445#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
446 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
447#endif
448#if defined(JSON_HEDLEY_INTEL_VERSION)
449 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
450#else
451 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
452#endif
453
454#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
455 #undef JSON_HEDLEY_INTEL_CL_VERSION
456#endif
457#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
458 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
459#endif
460
461#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
462 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
463#endif
464#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
465 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
466#else
467 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
468#endif
469
470#if defined(JSON_HEDLEY_PGI_VERSION)
471 #undef JSON_HEDLEY_PGI_VERSION
472#endif
473#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
474 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
475#endif
476
477#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
478 #undef JSON_HEDLEY_PGI_VERSION_CHECK
479#endif
480#if defined(JSON_HEDLEY_PGI_VERSION)
481 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
482#else
483 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
484#endif
485
486#if defined(JSON_HEDLEY_SUNPRO_VERSION)
487 #undef JSON_HEDLEY_SUNPRO_VERSION
488#endif
489#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
490 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
491#elif defined(__SUNPRO_C)
492 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
493#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
494 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
495#elif defined(__SUNPRO_CC)
496 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
497#endif
498
499#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
500 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
501#endif
502#if defined(JSON_HEDLEY_SUNPRO_VERSION)
503 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
504#else
505 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
506#endif
507
508#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
509 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
510#endif
511#if defined(__EMSCRIPTEN__)
512 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
513#endif
514
515#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
516 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
517#endif
518#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
519 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
520#else
521 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
522#endif
523
524#if defined(JSON_HEDLEY_ARM_VERSION)
525 #undef JSON_HEDLEY_ARM_VERSION
526#endif
527#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
528 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
529#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
530 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
531#endif
532
533#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
534 #undef JSON_HEDLEY_ARM_VERSION_CHECK
535#endif
536#if defined(JSON_HEDLEY_ARM_VERSION)
537 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
538#else
539 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
540#endif
541
542#if defined(JSON_HEDLEY_IBM_VERSION)
543 #undef JSON_HEDLEY_IBM_VERSION
544#endif
545#if defined(__ibmxl__)
546 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
547#elif defined(__xlC__) && defined(__xlC_ver__)
548 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
549#elif defined(__xlC__)
550 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
551#endif
552
553#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
554 #undef JSON_HEDLEY_IBM_VERSION_CHECK
555#endif
556#if defined(JSON_HEDLEY_IBM_VERSION)
557 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
558#else
559 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
560#endif
561
562#if defined(JSON_HEDLEY_TI_VERSION)
563 #undef JSON_HEDLEY_TI_VERSION
564#endif
565#if \
566 defined(__TI_COMPILER_VERSION__) && \
567 ( \
568 defined(__TMS470__) || defined(__TI_ARM__) || \
569 defined(__MSP430__) || \
570 defined(__TMS320C2000__) \
571 )
572#if (__TI_COMPILER_VERSION__ >= 16000000)
573 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
574#endif
575#endif
576
577#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
578 #undef JSON_HEDLEY_TI_VERSION_CHECK
579#endif
580#if defined(JSON_HEDLEY_TI_VERSION)
581 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
582#else
583 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
584#endif
585
586#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
587 #undef JSON_HEDLEY_TI_CL2000_VERSION
588#endif
589#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
590 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
591#endif
592
593#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
594 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
595#endif
596#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
597 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
598#else
599 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
600#endif
601
602#if defined(JSON_HEDLEY_TI_CL430_VERSION)
603 #undef JSON_HEDLEY_TI_CL430_VERSION
604#endif
605#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
606 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
607#endif
608
609#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
610 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
611#endif
612#if defined(JSON_HEDLEY_TI_CL430_VERSION)
613 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
614#else
615 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
616#endif
617
618#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
619 #undef JSON_HEDLEY_TI_ARMCL_VERSION
620#endif
621#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
622 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
623#endif
624
625#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
626 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
627#endif
628#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
629 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
630#else
631 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
632#endif
633
634#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
635 #undef JSON_HEDLEY_TI_CL6X_VERSION
636#endif
637#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
638 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
639#endif
640
641#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
642 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
643#endif
644#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
645 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
646#else
647 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
648#endif
649
650#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
651 #undef JSON_HEDLEY_TI_CL7X_VERSION
652#endif
653#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
654 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
655#endif
656
657#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
658 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
659#endif
660#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
661 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
662#else
663 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
664#endif
665
666#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
667 #undef JSON_HEDLEY_TI_CLPRU_VERSION
668#endif
669#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
670 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
671#endif
672
673#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
674 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
675#endif
676#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
677 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
678#else
679 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
680#endif
681
682#if defined(JSON_HEDLEY_CRAY_VERSION)
683 #undef JSON_HEDLEY_CRAY_VERSION
684#endif
685#if defined(_CRAYC)
686 #if defined(_RELEASE_PATCHLEVEL)
687 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
688 #else
689 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
690 #endif
691#endif
692
693#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
694 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
695#endif
696#if defined(JSON_HEDLEY_CRAY_VERSION)
697 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
698#else
699 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
700#endif
701
702#if defined(JSON_HEDLEY_IAR_VERSION)
703 #undef JSON_HEDLEY_IAR_VERSION
704#endif
705#if defined(__IAR_SYSTEMS_ICC__)
706 #if __VER__ > 1000
707 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
708 #else
709 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
710 #endif
711#endif
712
713#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
714 #undef JSON_HEDLEY_IAR_VERSION_CHECK
715#endif
716#if defined(JSON_HEDLEY_IAR_VERSION)
717 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
718#else
719 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
720#endif
721
722#if defined(JSON_HEDLEY_TINYC_VERSION)
723 #undef JSON_HEDLEY_TINYC_VERSION
724#endif
725#if defined(__TINYC__)
726 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
727#endif
728
729#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
730 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
731#endif
732#if defined(JSON_HEDLEY_TINYC_VERSION)
733 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
734#else
735 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
736#endif
737
738#if defined(JSON_HEDLEY_DMC_VERSION)
739 #undef JSON_HEDLEY_DMC_VERSION
740#endif
741#if defined(__DMC__)
742 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
743#endif
744
745#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
746 #undef JSON_HEDLEY_DMC_VERSION_CHECK
747#endif
748#if defined(JSON_HEDLEY_DMC_VERSION)
749 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
750#else
751 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
752#endif
753
754#if defined(JSON_HEDLEY_COMPCERT_VERSION)
755 #undef JSON_HEDLEY_COMPCERT_VERSION
756#endif
757#if defined(__COMPCERT_VERSION__)
758 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
759#endif
760
761#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
762 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
763#endif
764#if defined(JSON_HEDLEY_COMPCERT_VERSION)
765 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
766#else
767 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
768#endif
769
770#if defined(JSON_HEDLEY_PELLES_VERSION)
771 #undef JSON_HEDLEY_PELLES_VERSION
772#endif
773#if defined(__POCC__)
774 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
775#endif
776
777#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
778 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
779#endif
780#if defined(JSON_HEDLEY_PELLES_VERSION)
781 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
782#else
783 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
784#endif
785
786#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
787 #undef JSON_HEDLEY_MCST_LCC_VERSION
788#endif
789#if defined(__LCC__) && defined(__LCC_MINOR__)
790 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
791#endif
792
793#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
794 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
795#endif
796#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
797 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
798#else
799 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
800#endif
801
802#if defined(JSON_HEDLEY_GCC_VERSION)
803 #undef JSON_HEDLEY_GCC_VERSION
804#endif
805#if \
806 defined(JSON_HEDLEY_GNUC_VERSION) && \
807 !defined(__clang__) && \
808 !defined(JSON_HEDLEY_INTEL_VERSION) && \
809 !defined(JSON_HEDLEY_PGI_VERSION) && \
810 !defined(JSON_HEDLEY_ARM_VERSION) && \
811 !defined(JSON_HEDLEY_CRAY_VERSION) && \
812 !defined(JSON_HEDLEY_TI_VERSION) && \
813 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
814 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
815 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
816 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
817 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
818 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
819 !defined(__COMPCERT__) && \
820 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
821 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
822#endif
823
824#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
825 #undef JSON_HEDLEY_GCC_VERSION_CHECK
826#endif
827#if defined(JSON_HEDLEY_GCC_VERSION)
828 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
829#else
830 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
831#endif
832
833#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
834 #undef JSON_HEDLEY_HAS_ATTRIBUTE
835#endif
836#if \
837 defined(__has_attribute) && \
838 ( \
839 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
840 )
841# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
842#else
843# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
844#endif
845
846#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
847 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
848#endif
849#if defined(__has_attribute)
850 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
851#else
852 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
853#endif
854
855#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
856 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
857#endif
858#if defined(__has_attribute)
859 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
860#else
861 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
862#endif
863
864#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
865 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
866#endif
867#if \
868 defined(__has_cpp_attribute) && \
869 defined(__cplusplus) && \
870 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
871 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
872#else
873 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
874#endif
875
876#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
877 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
878#endif
879#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
881#elif \
882 !defined(JSON_HEDLEY_PGI_VERSION) && \
883 !defined(JSON_HEDLEY_IAR_VERSION) && \
884 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
885 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
886 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
887#else
888 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
889#endif
890
891#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
892 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
893#endif
894#if defined(__has_cpp_attribute) && defined(__cplusplus)
895 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
896#else
897 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
898#endif
899
900#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
901 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
902#endif
903#if defined(__has_cpp_attribute) && defined(__cplusplus)
904 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
905#else
906 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
907#endif
908
909#if defined(JSON_HEDLEY_HAS_BUILTIN)
910 #undef JSON_HEDLEY_HAS_BUILTIN
911#endif
912#if defined(__has_builtin)
913 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
914#else
915 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
916#endif
917
918#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
919 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
920#endif
921#if defined(__has_builtin)
922 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
923#else
924 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
925#endif
926
927#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
928 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
929#endif
930#if defined(__has_builtin)
931 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
932#else
933 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
934#endif
935
936#if defined(JSON_HEDLEY_HAS_FEATURE)
937 #undef JSON_HEDLEY_HAS_FEATURE
938#endif
939#if defined(__has_feature)
940 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
941#else
942 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
943#endif
944
945#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
946 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
947#endif
948#if defined(__has_feature)
949 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
950#else
951 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
952#endif
953
954#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
955 #undef JSON_HEDLEY_GCC_HAS_FEATURE
956#endif
957#if defined(__has_feature)
958 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
959#else
960 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
961#endif
962
963#if defined(JSON_HEDLEY_HAS_EXTENSION)
964 #undef JSON_HEDLEY_HAS_EXTENSION
965#endif
966#if defined(__has_extension)
967 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
968#else
969 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
970#endif
971
972#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
973 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
974#endif
975#if defined(__has_extension)
976 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
977#else
978 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
979#endif
980
981#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
982 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
983#endif
984#if defined(__has_extension)
985 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
986#else
987 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
988#endif
989
990#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
991 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
992#endif
993#if defined(__has_declspec_attribute)
994 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
995#else
996 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
997#endif
998
999#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1000 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1001#endif
1002#if defined(__has_declspec_attribute)
1003 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1004#else
1005 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1006#endif
1007
1008#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1009 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1010#endif
1011#if defined(__has_declspec_attribute)
1012 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1013#else
1014 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1015#endif
1016
1017#if defined(JSON_HEDLEY_HAS_WARNING)
1018 #undef JSON_HEDLEY_HAS_WARNING
1019#endif
1020#if defined(__has_warning)
1021 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1022#else
1023 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1024#endif
1025
1026#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1027 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1028#endif
1029#if defined(__has_warning)
1030 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1031#else
1032 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1033#endif
1034
1035#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1036 #undef JSON_HEDLEY_GCC_HAS_WARNING
1037#endif
1038#if defined(__has_warning)
1039 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1040#else
1041 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1042#endif
1043
1044#if \
1045 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1046 defined(__clang__) || \
1047 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1048 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1049 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1050 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1051 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1052 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1053 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1054 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1055 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1056 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1057 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1058 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1059 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1060 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1061 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1062 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1063 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1064#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1065 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1066#else
1067 #define JSON_HEDLEY_PRAGMA(value)
1068#endif
1069
1070#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1071 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1072#endif
1073#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1074 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1075#endif
1076#if defined(__clang__)
1077 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1078 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1079#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1080 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1081 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1082#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1083 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1084 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1085#elif \
1086 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1087 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1088 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1089 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1090#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1091 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1092 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1093#elif \
1094 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1095 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1096 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1097 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1098 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1099 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1100 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1101 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1102#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1103 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1104 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1105#else
1106 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1107 #define JSON_HEDLEY_DIAGNOSTIC_POP
1108#endif
1109
1110/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1111 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1112#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1113 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1114#endif
1115#if defined(__cplusplus)
1116# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1117# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1118# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1119# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1120 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1121 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1122 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1123 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1124 xpr \
1125 JSON_HEDLEY_DIAGNOSTIC_POP
1126# else
1127# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1128 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1129 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1130 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1131 xpr \
1132 JSON_HEDLEY_DIAGNOSTIC_POP
1133# endif
1134# else
1135# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1136 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1137 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1138 xpr \
1139 JSON_HEDLEY_DIAGNOSTIC_POP
1140# endif
1141# endif
1142#endif
1143#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1144 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1145#endif
1146
1147#if defined(JSON_HEDLEY_CONST_CAST)
1148 #undef JSON_HEDLEY_CONST_CAST
1149#endif
1150#if defined(__cplusplus)
1151# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1152#elif \
1153 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1154 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1155 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1156# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1157 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1158 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1159 ((T) (expr)); \
1160 JSON_HEDLEY_DIAGNOSTIC_POP \
1161 }))
1162#else
1163# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1164#endif
1165
1166#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1167 #undef JSON_HEDLEY_REINTERPRET_CAST
1168#endif
1169#if defined(__cplusplus)
1170 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1171#else
1172 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1173#endif
1174
1175#if defined(JSON_HEDLEY_STATIC_CAST)
1176 #undef JSON_HEDLEY_STATIC_CAST
1177#endif
1178#if defined(__cplusplus)
1179 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1180#else
1181 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1182#endif
1183
1184#if defined(JSON_HEDLEY_CPP_CAST)
1185 #undef JSON_HEDLEY_CPP_CAST
1186#endif
1187#if defined(__cplusplus)
1188# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1189# define JSON_HEDLEY_CPP_CAST(T, expr) \
1190 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1191 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1192 ((T) (expr)) \
1193 JSON_HEDLEY_DIAGNOSTIC_POP
1194# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1195# define JSON_HEDLEY_CPP_CAST(T, expr) \
1196 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1197 _Pragma("diag_suppress=Pe137") \
1198 JSON_HEDLEY_DIAGNOSTIC_POP
1199# else
1200# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1201# endif
1202#else
1203# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1204#endif
1205
1206#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1207 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1208#endif
1209#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1211#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1213#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1215#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1217#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1219#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1221#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1223#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1225#elif \
1226 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1227 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1228 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1229 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1230 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1231 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1232 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1233 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1234 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1235 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1236 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1238#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1240#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1242#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1244#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1245 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1246#else
1247 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1248#endif
1249
1250#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1251 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1252#endif
1253#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1255#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1257#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1259#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1261#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1262 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1263#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1265#elif \
1266 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1267 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1268 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1269 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1271#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1273#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1275#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1276 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1277#else
1278 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1279#endif
1280
1281#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1282 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1283#endif
1284#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1286#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1288#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1290#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1292#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1294#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1296#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1298#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1300#elif \
1301 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1302 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1303 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1305#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1307#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1308 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1309#else
1310 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1311#endif
1312
1313#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1314 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1315#endif
1316#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1318#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1320#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1321 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1322#else
1323 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1324#endif
1325
1326#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1327 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1328#endif
1329#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1331#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1333#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1335#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1336 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1337#else
1338 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1339#endif
1340
1341#if defined(JSON_HEDLEY_DEPRECATED)
1342 #undef JSON_HEDLEY_DEPRECATED
1343#endif
1344#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1345 #undef JSON_HEDLEY_DEPRECATED_FOR
1346#endif
1347#if \
1348 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1349 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1350 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1351 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1352#elif \
1353 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1354 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1355 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1356 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1357 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1358 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1359 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1360 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1361 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1362 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1363 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1364 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1365 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1366 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1367#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1368 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1369 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1370#elif \
1371 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1372 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1373 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1374 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1375 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1376 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1377 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1378 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1379 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1380 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1381 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1382 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1383 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1384 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1385 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1386 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1387 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1388 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1389#elif \
1390 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1391 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1392 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1393 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1394 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1395#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1396 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1397 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1398#else
1399 #define JSON_HEDLEY_DEPRECATED(since)
1400 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1401#endif
1402
1403#if defined(JSON_HEDLEY_UNAVAILABLE)
1404 #undef JSON_HEDLEY_UNAVAILABLE
1405#endif
1406#if \
1407 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1408 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1409 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1410 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1411 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1412#else
1413 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1414#endif
1415
1416#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1417 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1418#endif
1419#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1420 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1421#endif
1422#if \
1423 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1424 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1425 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1426 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1427 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1428 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1429 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1430 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1431 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1432 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1433 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1434 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1435 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1436 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1437 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1438 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1439 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1441 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1442#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1444 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1445#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1447 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1448#elif defined(_Check_return_) /* SAL */
1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1451#else
1452 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1454#endif
1455
1456#if defined(JSON_HEDLEY_SENTINEL)
1457 #undef JSON_HEDLEY_SENTINEL
1458#endif
1459#if \
1460 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1461 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1462 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1463 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1464 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1465 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1466#else
1467 #define JSON_HEDLEY_SENTINEL(position)
1468#endif
1469
1470#if defined(JSON_HEDLEY_NO_RETURN)
1471 #undef JSON_HEDLEY_NO_RETURN
1472#endif
1473#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1474 #define JSON_HEDLEY_NO_RETURN __noreturn
1475#elif \
1476 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1477 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1478 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1479#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1480 #define JSON_HEDLEY_NO_RETURN _Noreturn
1481#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1482 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1483#elif \
1484 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1485 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1486 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1487 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1488 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1489 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1490 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1492 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1493 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1494 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1495 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1496 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1497 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1498 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1499 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1500 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1501 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1502#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1503 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1504#elif \
1505 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1506 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1507 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1508#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1509 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1510#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1511 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1512#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1513 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1514#else
1515 #define JSON_HEDLEY_NO_RETURN
1516#endif
1517
1518#if defined(JSON_HEDLEY_NO_ESCAPE)
1519 #undef JSON_HEDLEY_NO_ESCAPE
1520#endif
1521#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1522 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1523#else
1524 #define JSON_HEDLEY_NO_ESCAPE
1525#endif
1526
1527#if defined(JSON_HEDLEY_UNREACHABLE)
1528 #undef JSON_HEDLEY_UNREACHABLE
1529#endif
1530#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1531 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1532#endif
1533#if defined(JSON_HEDLEY_ASSUME)
1534 #undef JSON_HEDLEY_ASSUME
1535#endif
1536#if \
1537 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1538 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1539 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1540 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1541#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1542 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1543#elif \
1544 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1545 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1546 #if defined(__cplusplus)
1547 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1548 #else
1549 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1550 #endif
1551#endif
1552#if \
1553 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1554 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1555 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1556 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1557 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1558 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1559 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1560 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1561#elif defined(JSON_HEDLEY_ASSUME)
1562 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1563#endif
1564#if !defined(JSON_HEDLEY_ASSUME)
1565 #if defined(JSON_HEDLEY_UNREACHABLE)
1566 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1567 #else
1568 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1569 #endif
1570#endif
1571#if defined(JSON_HEDLEY_UNREACHABLE)
1572 #if \
1573 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1574 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1575 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1576 #else
1577 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1578 #endif
1579#else
1580 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1581#endif
1582#if !defined(JSON_HEDLEY_UNREACHABLE)
1583 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1584#endif
1585
1587#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1588 #pragma clang diagnostic ignored "-Wpedantic"
1589#endif
1590#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1591 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1592#endif
1593#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1594 #if defined(__clang__)
1595 #pragma clang diagnostic ignored "-Wvariadic-macros"
1596 #elif defined(JSON_HEDLEY_GCC_VERSION)
1597 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1598 #endif
1599#endif
1600#if defined(JSON_HEDLEY_NON_NULL)
1601 #undef JSON_HEDLEY_NON_NULL
1602#endif
1603#if \
1604 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1605 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1606 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1607 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1608 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1609#else
1610 #define JSON_HEDLEY_NON_NULL(...)
1611#endif
1613
1614#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1615 #undef JSON_HEDLEY_PRINTF_FORMAT
1616#endif
1617#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1618 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1619#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1620 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1621#elif \
1622 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1623 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1624 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1625 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1626 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1627 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1628 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1629 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1630 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1631 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1632 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1633 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1634 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1635 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1636 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1637 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1638 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1640#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1641 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1642#else
1643 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1644#endif
1645
1646#if defined(JSON_HEDLEY_CONSTEXPR)
1647 #undef JSON_HEDLEY_CONSTEXPR
1648#endif
1649#if defined(__cplusplus)
1650 #if __cplusplus >= 201103L
1651 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1652 #endif
1653#endif
1654#if !defined(JSON_HEDLEY_CONSTEXPR)
1655 #define JSON_HEDLEY_CONSTEXPR
1656#endif
1657
1658#if defined(JSON_HEDLEY_PREDICT)
1659 #undef JSON_HEDLEY_PREDICT
1660#endif
1661#if defined(JSON_HEDLEY_LIKELY)
1662 #undef JSON_HEDLEY_LIKELY
1663#endif
1664#if defined(JSON_HEDLEY_UNLIKELY)
1665 #undef JSON_HEDLEY_UNLIKELY
1666#endif
1667#if defined(JSON_HEDLEY_UNPREDICTABLE)
1668 #undef JSON_HEDLEY_UNPREDICTABLE
1669#endif
1670#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1671 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1672#endif
1673#if \
1674 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1675 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1676 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1677# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1678# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1679# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1680# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1681# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1682#elif \
1683 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1684 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1685 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1686 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1687 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1688 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1689 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1690 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1691 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1692 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1693 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1694 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1695 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1696 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1697 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1698 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1699# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1700 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1701# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1702 (__extension__ ({ \
1703 double hedley_probability_ = (probability); \
1704 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1705 }))
1706# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1707 (__extension__ ({ \
1708 double hedley_probability_ = (probability); \
1709 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1710 }))
1711# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1712# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1713#else
1714# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1715# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1716# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1717# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1718# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1719#endif
1720#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1721 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1722#endif
1723
1724#if defined(JSON_HEDLEY_MALLOC)
1725 #undef JSON_HEDLEY_MALLOC
1726#endif
1727#if \
1728 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1729 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1730 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1731 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1732 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1733 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1734 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1735 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1736 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1737 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1738 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1739 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1740 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1741 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1742 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1743 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1744 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1745 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1746 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1747#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1748 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1749#elif \
1750 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1751 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1752 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1753#else
1754 #define JSON_HEDLEY_MALLOC
1755#endif
1756
1757#if defined(JSON_HEDLEY_PURE)
1758 #undef JSON_HEDLEY_PURE
1759#endif
1760#if \
1761 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1762 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1763 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1764 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1765 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1766 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1767 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1768 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1770 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1772 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1773 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1774 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1775 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1776 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1777 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1778 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1779 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1780# define JSON_HEDLEY_PURE __attribute__((__pure__))
1781#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1782# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1783#elif defined(__cplusplus) && \
1784 ( \
1785 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1786 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1787 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1788 )
1789# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1790#else
1791# define JSON_HEDLEY_PURE
1792#endif
1793
1794#if defined(JSON_HEDLEY_CONST)
1795 #undef JSON_HEDLEY_CONST
1796#endif
1797#if \
1798 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1799 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1800 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1801 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1802 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1803 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1804 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1805 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1806 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1807 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1808 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1809 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1810 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1811 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1812 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1813 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1814 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1815 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1816 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1817 #define JSON_HEDLEY_CONST __attribute__((__const__))
1818#elif \
1819 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1820 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1821#else
1822 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1823#endif
1824
1825#if defined(JSON_HEDLEY_RESTRICT)
1826 #undef JSON_HEDLEY_RESTRICT
1827#endif
1828#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1829 #define JSON_HEDLEY_RESTRICT restrict
1830#elif \
1831 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1832 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1833 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1834 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1835 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1836 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1837 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1838 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1839 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1840 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1841 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1842 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1843 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1844 defined(__clang__) || \
1845 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1846 #define JSON_HEDLEY_RESTRICT __restrict
1847#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1848 #define JSON_HEDLEY_RESTRICT _Restrict
1849#else
1850 #define JSON_HEDLEY_RESTRICT
1851#endif
1852
1853#if defined(JSON_HEDLEY_INLINE)
1854 #undef JSON_HEDLEY_INLINE
1855#endif
1856#if \
1857 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1858 (defined(__cplusplus) && (__cplusplus >= 199711L))
1859 #define JSON_HEDLEY_INLINE inline
1860#elif \
1861 defined(JSON_HEDLEY_GCC_VERSION) || \
1862 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1863 #define JSON_HEDLEY_INLINE __inline__
1864#elif \
1865 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1866 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1867 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1868 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1869 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1870 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1871 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1872 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1873 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1874 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1875 #define JSON_HEDLEY_INLINE __inline
1876#else
1877 #define JSON_HEDLEY_INLINE
1878#endif
1879
1880#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1881 #undef JSON_HEDLEY_ALWAYS_INLINE
1882#endif
1883#if \
1884 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1885 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1886 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1887 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1888 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1889 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1890 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1891 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1892 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1893 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1894 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1895 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1896 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1897 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1898 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1899 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1900 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1901 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1902 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1903# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1904#elif \
1905 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1906 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1907# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1908#elif defined(__cplusplus) && \
1909 ( \
1910 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1911 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1912 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1913 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1914 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1915 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1916 )
1917# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1918#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1919# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1920#else
1921# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1922#endif
1923
1924#if defined(JSON_HEDLEY_NEVER_INLINE)
1925 #undef JSON_HEDLEY_NEVER_INLINE
1926#endif
1927#if \
1928 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1929 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1930 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1931 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1932 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1933 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1934 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1935 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1936 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1937 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1938 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1939 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1940 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1941 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1942 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1943 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1944 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1945 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1946 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1947 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1948#elif \
1949 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1950 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1951 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1952#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1953 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1954#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1955 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1956#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1957 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1958#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1959 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1960#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1961 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1962#else
1963 #define JSON_HEDLEY_NEVER_INLINE
1964#endif
1965
1966#if defined(JSON_HEDLEY_PRIVATE)
1967 #undef JSON_HEDLEY_PRIVATE
1968#endif
1969#if defined(JSON_HEDLEY_PUBLIC)
1970 #undef JSON_HEDLEY_PUBLIC
1971#endif
1972#if defined(JSON_HEDLEY_IMPORT)
1973 #undef JSON_HEDLEY_IMPORT
1974#endif
1975#if defined(_WIN32) || defined(__CYGWIN__)
1976# define JSON_HEDLEY_PRIVATE
1977# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1978# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1979#else
1980# if \
1981 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1982 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1983 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1984 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1985 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1986 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1987 ( \
1988 defined(__TI_EABI__) && \
1989 ( \
1990 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1991 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1992 ) \
1993 ) || \
1994 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1995# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1996# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1997# else
1998# define JSON_HEDLEY_PRIVATE
1999# define JSON_HEDLEY_PUBLIC
2000# endif
2001# define JSON_HEDLEY_IMPORT extern
2002#endif
2003
2004#if defined(JSON_HEDLEY_NO_THROW)
2005 #undef JSON_HEDLEY_NO_THROW
2006#endif
2007#if \
2008 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2009 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2010 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2011 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2012 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2013#elif \
2014 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2015 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2016 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2017 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2018#else
2019 #define JSON_HEDLEY_NO_THROW
2020#endif
2021
2022#if defined(JSON_HEDLEY_FALL_THROUGH)
2023 #undef JSON_HEDLEY_FALL_THROUGH
2024#endif
2025#if \
2026 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2027 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2028 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2029 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2030#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2031 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2032#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2033 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2034#elif defined(__fallthrough) /* SAL */
2035 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2036#else
2037 #define JSON_HEDLEY_FALL_THROUGH
2038#endif
2039
2040#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2041 #undef JSON_HEDLEY_RETURNS_NON_NULL
2042#endif
2043#if \
2044 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2045 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2046 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2047 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2048#elif defined(_Ret_notnull_) /* SAL */
2049 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2050#else
2051 #define JSON_HEDLEY_RETURNS_NON_NULL
2052#endif
2053
2054#if defined(JSON_HEDLEY_ARRAY_PARAM)
2055 #undef JSON_HEDLEY_ARRAY_PARAM
2056#endif
2057#if \
2058 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2059 !defined(__STDC_NO_VLA__) && \
2060 !defined(__cplusplus) && \
2061 !defined(JSON_HEDLEY_PGI_VERSION) && \
2062 !defined(JSON_HEDLEY_TINYC_VERSION)
2063 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2064#else
2065 #define JSON_HEDLEY_ARRAY_PARAM(name)
2066#endif
2067
2068#if defined(JSON_HEDLEY_IS_CONSTANT)
2069 #undef JSON_HEDLEY_IS_CONSTANT
2070#endif
2071#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2072 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2073#endif
2074/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2075 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2076#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2077 #undef JSON_HEDLEY_IS_CONSTEXPR_
2078#endif
2079#if \
2080 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2081 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2082 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2083 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2084 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2085 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2086 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2087 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2088 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2089 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2090 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2091#endif
2092#if !defined(__cplusplus)
2093# if \
2094 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2095 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2096 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2097 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2098 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2099 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2100 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2101#if defined(__INTPTR_TYPE__)
2102 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2103#else
2104 #include <stdint.h>
2105 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2106#endif
2107# elif \
2108 ( \
2109 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2110 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2111 !defined(JSON_HEDLEY_PGI_VERSION) && \
2112 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2113 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2114 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2115 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2116 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2117 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2118#if defined(__INTPTR_TYPE__)
2119 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2120#else
2121 #include <stdint.h>
2122 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2123#endif
2124# elif \
2125 defined(JSON_HEDLEY_GCC_VERSION) || \
2126 defined(JSON_HEDLEY_INTEL_VERSION) || \
2127 defined(JSON_HEDLEY_TINYC_VERSION) || \
2128 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2129 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2130 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2131 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2132 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2133 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2134 defined(__clang__)
2135# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2136 sizeof(void) != \
2137 sizeof(*( \
2138 1 ? \
2139 ((void*) ((expr) * 0L) ) : \
2140((struct { char v[sizeof(void) * 2]; } *) 1) \
2141 ) \
2142 ) \
2143 )
2144# endif
2145#endif
2146#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2147 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2148 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2149 #endif
2150 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2151#else
2152 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2153 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2154 #endif
2155 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2156#endif
2157
2158#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2159 #undef JSON_HEDLEY_BEGIN_C_DECLS
2160#endif
2161#if defined(JSON_HEDLEY_END_C_DECLS)
2162 #undef JSON_HEDLEY_END_C_DECLS
2163#endif
2164#if defined(JSON_HEDLEY_C_DECL)
2165 #undef JSON_HEDLEY_C_DECL
2166#endif
2167#if defined(__cplusplus)
2168 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2169 #define JSON_HEDLEY_END_C_DECLS }
2170 #define JSON_HEDLEY_C_DECL extern "C"
2171#else
2172 #define JSON_HEDLEY_BEGIN_C_DECLS
2173 #define JSON_HEDLEY_END_C_DECLS
2174 #define JSON_HEDLEY_C_DECL
2175#endif
2176
2177#if defined(JSON_HEDLEY_STATIC_ASSERT)
2178 #undef JSON_HEDLEY_STATIC_ASSERT
2179#endif
2180#if \
2181 !defined(__cplusplus) && ( \
2182 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2183 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2184 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2185 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2186 defined(_Static_assert) \
2187 )
2188# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2189#elif \
2190 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2191 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2192 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2193# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2194#else
2195# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2196#endif
2197
2198#if defined(JSON_HEDLEY_NULL)
2199 #undef JSON_HEDLEY_NULL
2200#endif
2201#if defined(__cplusplus)
2202 #if __cplusplus >= 201103L
2203 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2204 #elif defined(NULL)
2205 #define JSON_HEDLEY_NULL NULL
2206 #else
2207 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2208 #endif
2209#elif defined(NULL)
2210 #define JSON_HEDLEY_NULL NULL
2211#else
2212 #define JSON_HEDLEY_NULL ((void*) 0)
2213#endif
2214
2215#if defined(JSON_HEDLEY_MESSAGE)
2216 #undef JSON_HEDLEY_MESSAGE
2217#endif
2218#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2219# define JSON_HEDLEY_MESSAGE(msg) \
2220 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2221 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2222 JSON_HEDLEY_PRAGMA(message msg) \
2223 JSON_HEDLEY_DIAGNOSTIC_POP
2224#elif \
2225 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2226 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2227# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2228#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2229# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2230#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2231# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2232#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2233# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2234#else
2235# define JSON_HEDLEY_MESSAGE(msg)
2236#endif
2237
2238#if defined(JSON_HEDLEY_WARNING)
2239 #undef JSON_HEDLEY_WARNING
2240#endif
2241#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2242# define JSON_HEDLEY_WARNING(msg) \
2243 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2244 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2245 JSON_HEDLEY_PRAGMA(clang warning msg) \
2246 JSON_HEDLEY_DIAGNOSTIC_POP
2247#elif \
2248 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2249 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2250 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2251# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2252#elif \
2253 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2254 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2255# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2256#else
2257# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2258#endif
2259
2260#if defined(JSON_HEDLEY_REQUIRE)
2261 #undef JSON_HEDLEY_REQUIRE
2262#endif
2263#if defined(JSON_HEDLEY_REQUIRE_MSG)
2264 #undef JSON_HEDLEY_REQUIRE_MSG
2265#endif
2266#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2267# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2268# define JSON_HEDLEY_REQUIRE(expr) \
2269 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2270 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2271 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2272 JSON_HEDLEY_DIAGNOSTIC_POP
2273# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2274 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2275 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2276 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2277 JSON_HEDLEY_DIAGNOSTIC_POP
2278# else
2279# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2280# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2281# endif
2282#else
2283# define JSON_HEDLEY_REQUIRE(expr)
2284# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2285#endif
2286
2287#if defined(JSON_HEDLEY_FLAGS)
2288 #undef JSON_HEDLEY_FLAGS
2289#endif
2290#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2291 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2292#else
2293 #define JSON_HEDLEY_FLAGS
2294#endif
2295
2296#if defined(JSON_HEDLEY_FLAGS_CAST)
2297 #undef JSON_HEDLEY_FLAGS_CAST
2298#endif
2299#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2300# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2301 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2302 _Pragma("warning(disable:188)") \
2303 ((T) (expr)); \
2304 JSON_HEDLEY_DIAGNOSTIC_POP \
2305 }))
2306#else
2307# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2308#endif
2309
2310#if defined(JSON_HEDLEY_EMPTY_BASES)
2311 #undef JSON_HEDLEY_EMPTY_BASES
2312#endif
2313#if \
2314 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2315 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2316 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2317#else
2318 #define JSON_HEDLEY_EMPTY_BASES
2319#endif
2320
2321/* Remaining macros are deprecated. */
2322
2323#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2324 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2325#endif
2326#if defined(__clang__)
2327 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2328#else
2329 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2330#endif
2331
2332#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2333 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2334#endif
2335#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2336
2337#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2338 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2339#endif
2340#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2341
2342#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2343 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2344#endif
2345#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2346
2347#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2348 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2349#endif
2350#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2351
2352#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2353 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2354#endif
2355#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2356
2357#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2358 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2359#endif
2360#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2361
2362#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2363 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2364#endif
2365#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2366
2367#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2368
2369
2370// This file contains all internal macro definitions (except those affecting ABI)
2371// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2372
2373// #include <nlohmann/detail/abi_macros.hpp>
2374
2375
2376// exclude unsupported compilers
2377#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2378 #if defined(__clang__)
2379 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2380 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2381 #endif
2382 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2383 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2384 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2385 #endif
2386 #endif
2387#endif
2388
2389// C++ language standard detection
2390// if the user manually specified the used c++ version this is skipped
2391#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2392 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2393 #define JSON_HAS_CPP_20
2394 #define JSON_HAS_CPP_17
2395 #define JSON_HAS_CPP_14
2396 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2397 #define JSON_HAS_CPP_17
2398 #define JSON_HAS_CPP_14
2399 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2400 #define JSON_HAS_CPP_14
2401 #endif
2402 // the cpp 11 flag is always specified because it is the minimal required version
2403 #define JSON_HAS_CPP_11
2404#endif
2405
2406#ifdef __has_include
2407 #if __has_include(<version>)
2408 #include <version>
2409 #endif
2410#endif
2411
2412#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2413 #ifdef JSON_HAS_CPP_17
2414 #if defined(__cpp_lib_filesystem)
2415 #define JSON_HAS_FILESYSTEM 1
2416 #elif defined(__cpp_lib_experimental_filesystem)
2417 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2418 #elif !defined(__has_include)
2419 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2420 #elif __has_include(<filesystem>)
2421 #define JSON_HAS_FILESYSTEM 1
2422 #elif __has_include(<experimental/filesystem>)
2423 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2424 #endif
2425
2426 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2427 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2428 #undef JSON_HAS_FILESYSTEM
2429 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2430 #endif
2431
2432 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2433 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2434 #undef JSON_HAS_FILESYSTEM
2435 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2436 #endif
2437
2438 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2439 #if defined(__clang_major__) && __clang_major__ < 7
2440 #undef JSON_HAS_FILESYSTEM
2441 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2442 #endif
2443
2444 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2445 #if defined(_MSC_VER) && _MSC_VER < 1914
2446 #undef JSON_HAS_FILESYSTEM
2447 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2448 #endif
2449
2450 // no filesystem support before iOS 13
2451 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2452 #undef JSON_HAS_FILESYSTEM
2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2454 #endif
2455
2456 // no filesystem support before macOS Catalina
2457 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2458 #undef JSON_HAS_FILESYSTEM
2459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2460 #endif
2461 #endif
2462#endif
2463
2464#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2465 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2466#endif
2467
2468#ifndef JSON_HAS_FILESYSTEM
2469 #define JSON_HAS_FILESYSTEM 0
2470#endif
2471
2472#ifndef JSON_HAS_THREE_WAY_COMPARISON
2473 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2474 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2475 #define JSON_HAS_THREE_WAY_COMPARISON 1
2476 #else
2477 #define JSON_HAS_THREE_WAY_COMPARISON 0
2478 #endif
2479#endif
2480
2481#ifndef JSON_HAS_RANGES
2482 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2483 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2484 #define JSON_HAS_RANGES 0
2485 #elif defined(__cpp_lib_ranges)
2486 #define JSON_HAS_RANGES 1
2487 #else
2488 #define JSON_HAS_RANGES 0
2489 #endif
2490#endif
2491
2492#ifndef JSON_HAS_STATIC_RTTI
2493 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2494 #define JSON_HAS_STATIC_RTTI 1
2495 #else
2496 #define JSON_HAS_STATIC_RTTI 0
2497 #endif
2498#endif
2499
2500#ifdef JSON_HAS_CPP_17
2501 #define JSON_INLINE_VARIABLE inline
2502#else
2503 #define JSON_INLINE_VARIABLE
2504#endif
2505
2506#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2507 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2508#else
2509 #define JSON_NO_UNIQUE_ADDRESS
2510#endif
2511
2512// disable documentation warnings on clang
2513#if defined(__clang__)
2514 #pragma clang diagnostic push
2515 #pragma clang diagnostic ignored "-Wdocumentation"
2516 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2517#endif
2518
2519// allow disabling exceptions
2520#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2521 #define JSON_THROW(exception) throw exception
2522 #define JSON_TRY try
2523 #define JSON_CATCH(exception) catch(exception)
2524 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2525#else
2526 #include <cstdlib>
2527 #define JSON_THROW(exception) std::abort()
2528 #define JSON_TRY if(true)
2529 #define JSON_CATCH(exception) if(false)
2530 #define JSON_INTERNAL_CATCH(exception) if(false)
2531#endif
2532
2533// override exception macros
2534#if defined(JSON_THROW_USER)
2535 #undef JSON_THROW
2536 #define JSON_THROW JSON_THROW_USER
2537#endif
2538#if defined(JSON_TRY_USER)
2539 #undef JSON_TRY
2540 #define JSON_TRY JSON_TRY_USER
2541#endif
2542#if defined(JSON_CATCH_USER)
2543 #undef JSON_CATCH
2544 #define JSON_CATCH JSON_CATCH_USER
2545 #undef JSON_INTERNAL_CATCH
2546 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2547#endif
2548#if defined(JSON_INTERNAL_CATCH_USER)
2549 #undef JSON_INTERNAL_CATCH
2550 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2551#endif
2552
2553// allow overriding assert
2554#if !defined(JSON_ASSERT)
2555 #include <cassert> // assert
2556 #define JSON_ASSERT(x) assert(x)
2557#endif
2558
2559// allow to access some private functions (needed by the test suite)
2560#if defined(JSON_TESTS_PRIVATE)
2561 #define JSON_PRIVATE_UNLESS_TESTED public
2562#else
2563 #define JSON_PRIVATE_UNLESS_TESTED private
2564#endif
2565
2571#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2572 template<typename BasicJsonType> \
2573 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2574 { \
2575 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2576 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2577 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2578 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2579 auto it = std::find_if(std::begin(m), std::end(m), \
2580 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2581 { \
2582 return ej_pair.first == e; \
2583 }); \
2584 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2585 } \
2586 template<typename BasicJsonType> \
2587 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2588 { \
2589 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2590 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2591 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2592 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2593 auto it = std::find_if(std::begin(m), std::end(m), \
2594 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2595 { \
2596 return ej_pair.second == j; \
2597 }); \
2598 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2599 }
2600
2601// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2602// may be removed in the future once the class is split.
2603
2604#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2605 template<template<typename, typename, typename...> class ObjectType, \
2606 template<typename, typename...> class ArrayType, \
2607 class StringType, class BooleanType, class NumberIntegerType, \
2608 class NumberUnsignedType, class NumberFloatType, \
2609 template<typename> class AllocatorType, \
2610 template<typename, typename = void> class JSONSerializer, \
2611 class BinaryType, \
2612 class CustomBaseClass>
2613
2614#define NLOHMANN_BASIC_JSON_TPL \
2615 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2616 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2617 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2618
2619// Macros to simplify conversion from/to types
2620
2621#define NLOHMANN_JSON_EXPAND( x ) x
2622#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2623#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2624 NLOHMANN_JSON_PASTE64, \
2625 NLOHMANN_JSON_PASTE63, \
2626 NLOHMANN_JSON_PASTE62, \
2627 NLOHMANN_JSON_PASTE61, \
2628 NLOHMANN_JSON_PASTE60, \
2629 NLOHMANN_JSON_PASTE59, \
2630 NLOHMANN_JSON_PASTE58, \
2631 NLOHMANN_JSON_PASTE57, \
2632 NLOHMANN_JSON_PASTE56, \
2633 NLOHMANN_JSON_PASTE55, \
2634 NLOHMANN_JSON_PASTE54, \
2635 NLOHMANN_JSON_PASTE53, \
2636 NLOHMANN_JSON_PASTE52, \
2637 NLOHMANN_JSON_PASTE51, \
2638 NLOHMANN_JSON_PASTE50, \
2639 NLOHMANN_JSON_PASTE49, \
2640 NLOHMANN_JSON_PASTE48, \
2641 NLOHMANN_JSON_PASTE47, \
2642 NLOHMANN_JSON_PASTE46, \
2643 NLOHMANN_JSON_PASTE45, \
2644 NLOHMANN_JSON_PASTE44, \
2645 NLOHMANN_JSON_PASTE43, \
2646 NLOHMANN_JSON_PASTE42, \
2647 NLOHMANN_JSON_PASTE41, \
2648 NLOHMANN_JSON_PASTE40, \
2649 NLOHMANN_JSON_PASTE39, \
2650 NLOHMANN_JSON_PASTE38, \
2651 NLOHMANN_JSON_PASTE37, \
2652 NLOHMANN_JSON_PASTE36, \
2653 NLOHMANN_JSON_PASTE35, \
2654 NLOHMANN_JSON_PASTE34, \
2655 NLOHMANN_JSON_PASTE33, \
2656 NLOHMANN_JSON_PASTE32, \
2657 NLOHMANN_JSON_PASTE31, \
2658 NLOHMANN_JSON_PASTE30, \
2659 NLOHMANN_JSON_PASTE29, \
2660 NLOHMANN_JSON_PASTE28, \
2661 NLOHMANN_JSON_PASTE27, \
2662 NLOHMANN_JSON_PASTE26, \
2663 NLOHMANN_JSON_PASTE25, \
2664 NLOHMANN_JSON_PASTE24, \
2665 NLOHMANN_JSON_PASTE23, \
2666 NLOHMANN_JSON_PASTE22, \
2667 NLOHMANN_JSON_PASTE21, \
2668 NLOHMANN_JSON_PASTE20, \
2669 NLOHMANN_JSON_PASTE19, \
2670 NLOHMANN_JSON_PASTE18, \
2671 NLOHMANN_JSON_PASTE17, \
2672 NLOHMANN_JSON_PASTE16, \
2673 NLOHMANN_JSON_PASTE15, \
2674 NLOHMANN_JSON_PASTE14, \
2675 NLOHMANN_JSON_PASTE13, \
2676 NLOHMANN_JSON_PASTE12, \
2677 NLOHMANN_JSON_PASTE11, \
2678 NLOHMANN_JSON_PASTE10, \
2679 NLOHMANN_JSON_PASTE9, \
2680 NLOHMANN_JSON_PASTE8, \
2681 NLOHMANN_JSON_PASTE7, \
2682 NLOHMANN_JSON_PASTE6, \
2683 NLOHMANN_JSON_PASTE5, \
2684 NLOHMANN_JSON_PASTE4, \
2685 NLOHMANN_JSON_PASTE3, \
2686 NLOHMANN_JSON_PASTE2, \
2687 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2688#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2689#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2690#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2691#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2692#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2693#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2694#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2695#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2696#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2697#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2698#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2699#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2700#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2701#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2702#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2703#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2704#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2705#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2706#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2707#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2708#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2709#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2710#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2711#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2712#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2713#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2714#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2715#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2716#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2717#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2718#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2719#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2720#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2721#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2722#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2723#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2724#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2725#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2726#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2727#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2728#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2729#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2730#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2731#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2732#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2733#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2734#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2735#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2736#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2737#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2738#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2739#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2740#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2741#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2742#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2743#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2744#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2745#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2746#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2747#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2748#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2749#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2750#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2751
2752#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2753#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2754#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2755
2761#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2762 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2763 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2764
2765#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2766 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2767 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2768
2769#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2770 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2771
2777#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2778 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2779 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2780
2781#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2782 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2783
2784#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2785 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2786 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2787
2793#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2794 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2795 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2796
2797#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2798 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2799 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2800
2806#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2807 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2808 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2809
2810#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2811 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2812 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2813
2814// inspired from https://stackoverflow.com/a/26745591
2815// allows to call any std function as if (e.g. with begin):
2816// using std::begin; begin(x);
2817//
2818// it allows using the detected idiom to retrieve the return type
2819// of such an expression
2820#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2821 namespace detail { \
2822 using std::std_name; \
2823 \
2824 template<typename... T> \
2825 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2826 } \
2827 \
2828 namespace detail2 { \
2829 struct std_name##_tag \
2830 { \
2831 }; \
2832 \
2833 template<typename... T> \
2834 std_name##_tag std_name(T&&...); \
2835 \
2836 template<typename... T> \
2837 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2838 \
2839 template<typename... T> \
2840 struct would_call_std_##std_name \
2841 { \
2842 static constexpr auto const value = ::nlohmann::detail:: \
2843 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2844 }; \
2845 } /* namespace detail2 */ \
2846 \
2847 template<typename... T> \
2848 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2849 { \
2850 }
2851
2852#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2853 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2854#endif
2855
2856#if JSON_USE_IMPLICIT_CONVERSIONS
2857 #define JSON_EXPLICIT
2858#else
2859 #define JSON_EXPLICIT explicit
2860#endif
2861
2862#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2863 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2864#endif
2865
2866#ifndef JSON_USE_GLOBAL_UDLS
2867 #define JSON_USE_GLOBAL_UDLS 1
2868#endif
2869
2870#if JSON_HAS_THREE_WAY_COMPARISON
2871 #include <compare> // partial_ordering
2872#endif
2873
2875namespace detail
2876{
2877
2879// JSON type enumeration //
2881
2906enum class value_t : std::uint8_t
2907{
2908 null,
2909 object,
2910 array,
2911 string,
2912 boolean,
2915 number_float,
2916 binary,
2917 discarded
2918};
2919
2933#if JSON_HAS_THREE_WAY_COMPARISON
2934 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2935#else
2936 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2937#endif
2938{
2939 static constexpr std::array<std::uint8_t, 9> order = {{
2940 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2941 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2942 6 /* binary */
2943 }
2944 };
2945
2946 const auto l_index = static_cast<std::size_t>(lhs);
2947 const auto r_index = static_cast<std::size_t>(rhs);
2948#if JSON_HAS_THREE_WAY_COMPARISON
2949 if (l_index < order.size() && r_index < order.size())
2950 {
2951 return order[l_index] <=> order[r_index]; // *NOPAD*
2952 }
2953 return std::partial_ordering::unordered;
2954#else
2955 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2956#endif
2957}
2958
2959// GCC selects the built-in operator< over an operator rewritten from
2960// a user-defined spaceship operator
2961// Clang, MSVC, and ICC select the rewritten candidate
2962// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2963#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2964inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2965{
2966 return std::is_lt(lhs <=> rhs); // *NOPAD*
2967}
2968#endif
2969
2970} // namespace detail
2972
2973// #include <nlohmann/detail/string_escape.hpp>
2974// __ _____ _____ _____
2975// __| | __| | | | JSON for Modern C++
2976// | | |__ | | | | | | version 3.11.3
2977// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2978//
2979// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
2980// SPDX-License-Identifier: MIT
2981
2982
2983
2984// #include <nlohmann/detail/abi_macros.hpp>
2985
2986
2988namespace detail
2989{
2990
3004template<typename StringType>
3005inline void replace_substring(StringType& s, const StringType& f,
3006 const StringType& t)
3007{
3008 JSON_ASSERT(!f.empty());
3009 for (auto pos = s.find(f); // find first occurrence of f
3010 pos != StringType::npos; // make sure f was found
3011 s.replace(pos, f.size(), t), // replace with t, and
3012 pos = s.find(f, pos + t.size())) // find next occurrence of f
3013 {}
3014}
3015
3023template<typename StringType>
3024inline StringType escape(StringType s)
3025{
3026 replace_substring(s, StringType{"~"}, StringType{"~0"});
3027 replace_substring(s, StringType{"/"}, StringType{"~1"});
3028 return s;
3029}
3030
3038template<typename StringType>
3039static void unescape(StringType& s)
3040{
3041 replace_substring(s, StringType{"~1"}, StringType{"/"});
3042 replace_substring(s, StringType{"~0"}, StringType{"~"});
3043}
3044
3045} // namespace detail
3047
3048// #include <nlohmann/detail/input/position_t.hpp>
3049// __ _____ _____ _____
3050// __| | __| | | | JSON for Modern C++
3051// | | |__ | | | | | | version 3.11.3
3052// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3053//
3054// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3055// SPDX-License-Identifier: MIT
3056
3057
3058
3059#include <cstddef> // size_t
3060
3061// #include <nlohmann/detail/abi_macros.hpp>
3062
3063
3065namespace detail
3066{
3067
3070{
3072 std::size_t chars_read_total = 0;
3076 std::size_t lines_read = 0;
3077
3079 constexpr operator size_t() const
3080 {
3081 return chars_read_total;
3082 }
3083};
3084
3085} // namespace detail
3087
3088// #include <nlohmann/detail/macro_scope.hpp>
3089
3090// #include <nlohmann/detail/meta/cpp_future.hpp>
3091// __ _____ _____ _____
3092// __| | __| | | | JSON for Modern C++
3093// | | |__ | | | | | | version 3.11.3
3094// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3095//
3096// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3097// SPDX-FileCopyrightText: 2018 The Abseil Authors
3098// SPDX-License-Identifier: MIT
3099
3100
3101
3102#include <array> // array
3103#include <cstddef> // size_t
3104#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3105#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3106
3107// #include <nlohmann/detail/macro_scope.hpp>
3108
3109
3111namespace detail
3112{
3113
3114template<typename T>
3115using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3116
3117#ifdef JSON_HAS_CPP_14
3118
3119// the following utilities are natively available in C++14
3120using std::enable_if_t;
3121using std::index_sequence;
3122using std::make_index_sequence;
3123using std::index_sequence_for;
3124
3125#else
3126
3127// alias templates to reduce boilerplate
3128template<bool B, typename T = void>
3129using enable_if_t = typename std::enable_if<B, T>::type;
3130
3131// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3132// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3133
3135
3136// integer_sequence
3137//
3138// Class template representing a compile-time integer sequence. An instantiation
3139// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3140// type through its template arguments (which is a common need when
3141// working with C++11 variadic templates). `absl::integer_sequence` is designed
3142// to be a drop-in replacement for C++14's `std::integer_sequence`.
3143//
3144// Example:
3145//
3146// template< class T, T... Ints >
3147// void user_function(integer_sequence<T, Ints...>);
3148//
3149// int main()
3150// {
3151// // user_function's `T` will be deduced to `int` and `Ints...`
3152// // will be deduced to `0, 1, 2, 3, 4`.
3153// user_function(make_integer_sequence<int, 5>());
3154// }
3155template <typename T, T... Ints>
3157{
3158 using value_type = T;
3159 static constexpr std::size_t size() noexcept
3160 {
3161 return sizeof...(Ints);
3162 }
3163};
3164
3165// index_sequence
3166//
3167// A helper template for an `integer_sequence` of `size_t`,
3168// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3169// `std::index_sequence`.
3170template <size_t... Ints>
3171using index_sequence = integer_sequence<size_t, Ints...>;
3172
3173namespace utility_internal
3174{
3175
3176template <typename Seq, size_t SeqSize, size_t Rem>
3177struct Extend;
3178
3179// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3180template <typename T, T... Ints, size_t SeqSize>
3181struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3182{
3183 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3184};
3185
3186template <typename T, T... Ints, size_t SeqSize>
3187struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3188{
3189 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3190};
3191
3192// Recursion helper for 'make_integer_sequence<T, N>'.
3193// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3194template <typename T, size_t N>
3195struct Gen
3196{
3197 using type =
3198 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3199};
3200
3201template <typename T>
3202struct Gen<T, 0>
3203{
3205};
3206
3207} // namespace utility_internal
3208
3209// Compile-time sequences of integers
3210
3211// make_integer_sequence
3212//
3213// This template alias is equivalent to
3214// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3215// replacement for C++14's `std::make_integer_sequence`.
3216template <typename T, T N>
3218
3219// make_index_sequence
3220//
3221// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3222// and is designed to be a drop-in replacement for C++14's
3223// `std::make_index_sequence`.
3224template <size_t N>
3226
3227// index_sequence_for
3228//
3229// Converts a typename pack into an index sequence of the same length, and
3230// is designed to be a drop-in replacement for C++14's
3231// `std::index_sequence_for()`
3232template <typename... Ts>
3234
3236
3237#endif
3238
3239// dispatch utility (taken from ranges-v3)
3240template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3241template<> struct priority_tag<0> {};
3242
3243// taken from ranges-v3
3244template<typename T>
3246{
3247 static JSON_INLINE_VARIABLE constexpr T value{};
3248};
3249
3250#ifndef JSON_HAS_CPP_17
3251 template<typename T>
3252 constexpr T static_const<T>::value;
3253#endif
3254
3255template<typename T, typename... Args>
3256constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3257{
3258 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3259}
3260
3261} // namespace detail
3263
3264// #include <nlohmann/detail/meta/type_traits.hpp>
3265// __ _____ _____ _____
3266// __| | __| | | | JSON for Modern C++
3267// | | |__ | | | | | | version 3.11.3
3268// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3269//
3270// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3271// SPDX-License-Identifier: MIT
3272
3273
3274
3275#include <limits> // numeric_limits
3276#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3277#include <utility> // declval
3278#include <tuple> // tuple
3279#include <string> // char_traits
3280
3281// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3282// __ _____ _____ _____
3283// __| | __| | | | JSON for Modern C++
3284// | | |__ | | | | | | version 3.11.3
3285// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3286//
3287// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3288// SPDX-License-Identifier: MIT
3289
3290
3291
3292#include <iterator> // random_access_iterator_tag
3293
3294// #include <nlohmann/detail/abi_macros.hpp>
3295
3296// #include <nlohmann/detail/meta/void_t.hpp>
3297
3298// #include <nlohmann/detail/meta/cpp_future.hpp>
3299
3300
3302namespace detail
3303{
3304
3305template<typename It, typename = void>
3307
3308template<typename It>
3310 It,
3311 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3312 typename It::reference, typename It::iterator_category >>
3313{
3314 using difference_type = typename It::difference_type;
3315 using value_type = typename It::value_type;
3316 using pointer = typename It::pointer;
3317 using reference = typename It::reference;
3318 using iterator_category = typename It::iterator_category;
3319};
3320
3321// This is required as some compilers implement std::iterator_traits in a way that
3322// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3323template<typename T, typename = void>
3325{
3326};
3327
3328template<typename T>
3329struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3330 : iterator_types<T>
3331{
3332};
3333
3334template<typename T>
3336{
3337 using iterator_category = std::random_access_iterator_tag;
3338 using value_type = T;
3339 using difference_type = ptrdiff_t;
3340 using pointer = T*;
3341 using reference = T&;
3342};
3343
3344} // namespace detail
3346
3347// #include <nlohmann/detail/macro_scope.hpp>
3348
3349// #include <nlohmann/detail/meta/call_std/begin.hpp>
3350// __ _____ _____ _____
3351// __| | __| | | | JSON for Modern C++
3352// | | |__ | | | | | | version 3.11.3
3353// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3354//
3355// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3356// SPDX-License-Identifier: MIT
3357
3358
3359
3360// #include <nlohmann/detail/macro_scope.hpp>
3361
3362
3364
3366
3368
3369// #include <nlohmann/detail/meta/call_std/end.hpp>
3370// __ _____ _____ _____
3371// __| | __| | | | JSON for Modern C++
3372// | | |__ | | | | | | version 3.11.3
3373// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3374//
3375// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3376// SPDX-License-Identifier: MIT
3377
3378
3379
3380// #include <nlohmann/detail/macro_scope.hpp>
3381
3382
3384
3386
3388
3389// #include <nlohmann/detail/meta/cpp_future.hpp>
3390
3391// #include <nlohmann/detail/meta/detected.hpp>
3392
3393// #include <nlohmann/json_fwd.hpp>
3394// __ _____ _____ _____
3395// __| | __| | | | JSON for Modern C++
3396// | | |__ | | | | | | version 3.11.3
3397// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3398//
3399// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3400// SPDX-License-Identifier: MIT
3401
3402#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3403 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3404
3405 #include <cstdint> // int64_t, uint64_t
3406 #include <map> // map
3407 #include <memory> // allocator
3408 #include <string> // string
3409 #include <vector> // vector
3410
3411 // #include <nlohmann/detail/abi_macros.hpp>
3412
3413
3420
3428 template<typename T = void, typename SFINAE = void>
3429 struct adl_serializer;
3430
3433 template<template<typename U, typename V, typename... Args> class ObjectType =
3434 std::map,
3435 template<typename U, typename... Args> class ArrayType = std::vector,
3436 class StringType = std::string, class BooleanType = bool,
3437 class NumberIntegerType = std::int64_t,
3438 class NumberUnsignedType = std::uint64_t,
3439 class NumberFloatType = double,
3440 template<typename U> class AllocatorType = std::allocator,
3441 template<typename T, typename SFINAE = void> class JSONSerializer =
3443 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3444 class CustomBaseClass = void>
3445 class basic_json;
3446
3449 template<typename RefStringType>
3450 class json_pointer;
3451
3457
3460 template<class Key, class T, class IgnoredLess, class Allocator>
3461 struct ordered_map;
3462
3466
3468
3469#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3470
3471
3481namespace detail
3482{
3483
3485// helpers //
3487
3488// Note to maintainers:
3489//
3490// Every trait in this file expects a non CV-qualified type.
3491// The only exceptions are in the 'aliases for detected' section
3492// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3493//
3494// In this case, T has to be properly CV-qualified to constraint the function arguments
3495// (e.g. to_json(BasicJsonType&, const T&))
3496
3497template<typename> struct is_basic_json : std::false_type {};
3498
3500struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3501
3502// used by exceptions create() member functions
3503// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3504// false_type otherwise
3505template<typename BasicJsonContext>
3507 std::integral_constant < bool,
3508 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3509 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3510{};
3511
3513// json_ref helpers //
3515
3516template<typename>
3517class json_ref;
3518
3519template<typename>
3520struct is_json_ref : std::false_type {};
3521
3522template<typename T>
3523struct is_json_ref<json_ref<T>> : std::true_type {};
3524
3526// aliases for detected //
3528
3529template<typename T>
3530using mapped_type_t = typename T::mapped_type;
3531
3532template<typename T>
3533using key_type_t = typename T::key_type;
3534
3535template<typename T>
3536using value_type_t = typename T::value_type;
3537
3538template<typename T>
3539using difference_type_t = typename T::difference_type;
3540
3541template<typename T>
3542using pointer_t = typename T::pointer;
3543
3544template<typename T>
3545using reference_t = typename T::reference;
3546
3547template<typename T>
3548using iterator_category_t = typename T::iterator_category;
3549
3550template<typename T, typename... Args>
3551using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3552
3553template<typename T, typename... Args>
3554using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3555
3556template<typename T, typename U>
3557using get_template_function = decltype(std::declval<T>().template get<U>());
3558
3559// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3560template<typename BasicJsonType, typename T, typename = void>
3561struct has_from_json : std::false_type {};
3562
3563// trait checking if j.get<T> is valid
3564// use this trait instead of std::is_constructible or std::is_convertible,
3565// both rely on, or make use of implicit conversions, and thus fail when T
3566// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3567template <typename BasicJsonType, typename T>
3572
3573template<typename BasicJsonType, typename T>
3574struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3575{
3576 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3577
3578 static constexpr bool value =
3580 const BasicJsonType&, T&>::value;
3581};
3582
3583// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3584// this overload is used for non-default-constructible user-defined-types
3585template<typename BasicJsonType, typename T, typename = void>
3586struct has_non_default_from_json : std::false_type {};
3587
3588template<typename BasicJsonType, typename T>
3589struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3590{
3591 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3592
3593 static constexpr bool value =
3595 const BasicJsonType&>::value;
3596};
3597
3598// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3599// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3600template<typename BasicJsonType, typename T, typename = void>
3601struct has_to_json : std::false_type {};
3602
3603template<typename BasicJsonType, typename T>
3604struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3605{
3606 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3607
3608 static constexpr bool value =
3610 T>::value;
3611};
3612
3613template<typename T>
3614using detect_key_compare = typename T::key_compare;
3615
3616template<typename T>
3617struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3618
3619// obtains the actual object key comparator
3620template<typename BasicJsonType>
3622{
3623 using object_t = typename BasicJsonType::object_t;
3624 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3625 using type = typename std::conditional < has_key_compare<object_t>::value,
3626 typename object_t::key_compare, object_comparator_t>::type;
3627};
3628
3629template<typename BasicJsonType>
3631
3633// char_traits //
3635
3636// Primary template of char_traits calls std char_traits
3637template<typename T>
3638struct char_traits : std::char_traits<T>
3639{};
3640
3641// Explicitly define char traits for unsigned char since it is not standard
3642template<>
3643struct char_traits<unsigned char> : std::char_traits<char>
3644{
3645 using char_type = unsigned char;
3646 using int_type = uint64_t;
3647
3648 // Redefine to_int_type function
3649 static int_type to_int_type(char_type c) noexcept
3650 {
3651 return static_cast<int_type>(c);
3652 }
3653
3655 {
3656 return static_cast<char_type>(i);
3657 }
3658
3659 static constexpr int_type eof() noexcept
3660 {
3661 return static_cast<int_type>(EOF);
3662 }
3663};
3664
3665// Explicitly define char traits for signed char since it is not standard
3666template<>
3667struct char_traits<signed char> : std::char_traits<char>
3668{
3669 using char_type = signed char;
3670 using int_type = uint64_t;
3671
3672 // Redefine to_int_type function
3673 static int_type to_int_type(char_type c) noexcept
3674 {
3675 return static_cast<int_type>(c);
3676 }
3677
3679 {
3680 return static_cast<char_type>(i);
3681 }
3682
3683 static constexpr int_type eof() noexcept
3684 {
3685 return static_cast<int_type>(EOF);
3686 }
3687};
3688
3690// is_ functions //
3692
3693// https://en.cppreference.com/w/cpp/types/conjunction
3694template<class...> struct conjunction : std::true_type { };
3695template<class B> struct conjunction<B> : B { };
3696template<class B, class... Bn>
3697struct conjunction<B, Bn...>
3698: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3699
3700// https://en.cppreference.com/w/cpp/types/negation
3701template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3702
3703// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3704// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3705// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3706template <typename T>
3707struct is_default_constructible : std::is_default_constructible<T> {};
3708
3709template <typename T1, typename T2>
3710struct is_default_constructible<std::pair<T1, T2>>
3711 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3712
3713template <typename T1, typename T2>
3714struct is_default_constructible<const std::pair<T1, T2>>
3715 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3716
3717template <typename... Ts>
3718struct is_default_constructible<std::tuple<Ts...>>
3719 : conjunction<is_default_constructible<Ts>...> {};
3720
3721template <typename... Ts>
3722struct is_default_constructible<const std::tuple<Ts...>>
3723 : conjunction<is_default_constructible<Ts>...> {};
3724
3725template <typename T, typename... Args>
3726struct is_constructible : std::is_constructible<T, Args...> {};
3727
3728template <typename T1, typename T2>
3729struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3730
3731template <typename T1, typename T2>
3732struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3733
3734template <typename... Ts>
3735struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3736
3737template <typename... Ts>
3738struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3739
3740template<typename T, typename = void>
3741struct is_iterator_traits : std::false_type {};
3742
3743template<typename T>
3757
3758template<typename T>
3760{
3761 private:
3762 using t_ref = typename std::add_lvalue_reference<T>::type;
3763
3764 using iterator = detected_t<result_of_begin, t_ref>;
3765 using sentinel = detected_t<result_of_end, t_ref>;
3766
3767 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3768 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3769 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3770 static constexpr auto is_iterator_begin =
3772
3773 public:
3774 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3775};
3776
3777template<typename R>
3778using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3779
3780template<typename T>
3782
3783// The following implementation of is_complete_type is taken from
3784// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3785// and is written by Xiang Fan who agreed to using it in this library.
3786
3787template<typename T, typename = void>
3788struct is_complete_type : std::false_type {};
3789
3790template<typename T>
3791struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3792
3793template<typename BasicJsonType, typename CompatibleObjectType,
3794 typename = void>
3795struct is_compatible_object_type_impl : std::false_type {};
3796
3797template<typename BasicJsonType, typename CompatibleObjectType>
3799 BasicJsonType, CompatibleObjectType,
3800 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3801 is_detected<key_type_t, CompatibleObjectType>::value >>
3802{
3803 using object_t = typename BasicJsonType::object_t;
3804
3805 // macOS's is_constructible does not play well with nonesuch...
3806 static constexpr bool value =
3807 is_constructible<typename object_t::key_type,
3808 typename CompatibleObjectType::key_type>::value &&
3809 is_constructible<typename object_t::mapped_type,
3810 typename CompatibleObjectType::mapped_type>::value;
3811};
3812
3813template<typename BasicJsonType, typename CompatibleObjectType>
3815 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3816
3817template<typename BasicJsonType, typename ConstructibleObjectType,
3818 typename = void>
3819struct is_constructible_object_type_impl : std::false_type {};
3820
3821template<typename BasicJsonType, typename ConstructibleObjectType>
3823 BasicJsonType, ConstructibleObjectType,
3824 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3825 is_detected<key_type_t, ConstructibleObjectType>::value >>
3826{
3827 using object_t = typename BasicJsonType::object_t;
3828
3829 static constexpr bool value =
3831 (std::is_move_assignable<ConstructibleObjectType>::value ||
3832 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3833 (is_constructible<typename ConstructibleObjectType::key_type,
3834 typename object_t::key_type>::value &&
3835 std::is_same <
3836 typename object_t::mapped_type,
3837 typename ConstructibleObjectType::mapped_type >::value)) ||
3838 (has_from_json<BasicJsonType,
3839 typename ConstructibleObjectType::mapped_type>::value ||
3841 BasicJsonType,
3842 typename ConstructibleObjectType::mapped_type >::value);
3843};
3844
3845template<typename BasicJsonType, typename ConstructibleObjectType>
3847 : is_constructible_object_type_impl<BasicJsonType,
3848 ConstructibleObjectType> {};
3849
3850template<typename BasicJsonType, typename CompatibleStringType>
3856
3857template<typename BasicJsonType, typename ConstructibleStringType>
3859{
3860 // launder type through decltype() to fix compilation failure on ICPC
3861#ifdef __INTEL_COMPILER
3862 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3863#else
3864 using laundered_type = ConstructibleStringType;
3865#endif
3866
3867 static constexpr auto value =
3868 conjunction <
3870 is_detected_exact<typename BasicJsonType::string_t::value_type,
3872};
3873
3874template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3875struct is_compatible_array_type_impl : std::false_type {};
3876
3877template<typename BasicJsonType, typename CompatibleArrayType>
3879 BasicJsonType, CompatibleArrayType,
3880 enable_if_t <
3881 is_detected<iterator_t, CompatibleArrayType>::value&&
3882 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3883// special case for types like std::filesystem::path whose iterator's value_type are themselves
3884// c.f. https://github.com/nlohmann/json/pull/3073
3885 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3886{
3887 static constexpr bool value =
3888 is_constructible<BasicJsonType,
3890};
3891
3892template<typename BasicJsonType, typename CompatibleArrayType>
3894 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3895
3896template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3897struct is_constructible_array_type_impl : std::false_type {};
3898
3899template<typename BasicJsonType, typename ConstructibleArrayType>
3901 BasicJsonType, ConstructibleArrayType,
3902 enable_if_t<std::is_same<ConstructibleArrayType,
3903 typename BasicJsonType::value_type>::value >>
3904 : std::true_type {};
3905
3906template<typename BasicJsonType, typename ConstructibleArrayType>
3908 BasicJsonType, ConstructibleArrayType,
3909 enable_if_t < !std::is_same<ConstructibleArrayType,
3910 typename BasicJsonType::value_type>::value&&
3911 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3912 is_default_constructible<ConstructibleArrayType>::value&&
3913(std::is_move_assignable<ConstructibleArrayType>::value ||
3914 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3915is_detected<iterator_t, ConstructibleArrayType>::value&&
3916is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3917is_detected<range_value_t, ConstructibleArrayType>::value&&
3918// special case for types like std::filesystem::path whose iterator's value_type are themselves
3919// c.f. https://github.com/nlohmann/json/pull/3073
3920!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3922 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3923{
3925
3926 static constexpr bool value =
3927 std::is_same<value_type,
3928 typename BasicJsonType::array_t::value_type>::value ||
3929 has_from_json<BasicJsonType,
3932 BasicJsonType,
3934};
3935
3936template<typename BasicJsonType, typename ConstructibleArrayType>
3938 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3939
3940template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3941 typename = void>
3942struct is_compatible_integer_type_impl : std::false_type {};
3943
3944template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3946 RealIntegerType, CompatibleNumberIntegerType,
3947 enable_if_t < std::is_integral<RealIntegerType>::value&&
3948 std::is_integral<CompatibleNumberIntegerType>::value&&
3949 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3950{
3951 // is there an assert somewhere on overflows?
3952 using RealLimits = std::numeric_limits<RealIntegerType>;
3953 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3954
3955 static constexpr auto value =
3956 is_constructible<RealIntegerType,
3957 CompatibleNumberIntegerType>::value &&
3958 CompatibleLimits::is_integer &&
3959 RealLimits::is_signed == CompatibleLimits::is_signed;
3960};
3961
3962template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3964 : is_compatible_integer_type_impl<RealIntegerType,
3965 CompatibleNumberIntegerType> {};
3966
3967template<typename BasicJsonType, typename CompatibleType, typename = void>
3968struct is_compatible_type_impl: std::false_type {};
3969
3970template<typename BasicJsonType, typename CompatibleType>
3972 BasicJsonType, CompatibleType,
3973 enable_if_t<is_complete_type<CompatibleType>::value >>
3974{
3975 static constexpr bool value =
3977};
3978
3979template<typename BasicJsonType, typename CompatibleType>
3981 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3982
3983template<typename T1, typename T2>
3984struct is_constructible_tuple : std::false_type {};
3985
3986template<typename T1, typename... Args>
3987struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3988
3989template<typename BasicJsonType, typename T>
3990struct is_json_iterator_of : std::false_type {};
3991
3992template<typename BasicJsonType>
3993struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3994
3995template<typename BasicJsonType>
3996struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3997{};
3998
3999// checks if a given type T is a template specialization of Primary
4000template<template <typename...> class Primary, typename T>
4001struct is_specialization_of : std::false_type {};
4002
4003template<template <typename...> class Primary, typename... Args>
4004struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4005
4006template<typename T>
4008
4009// checks if A and B are comparable using Compare functor
4010template<typename Compare, typename A, typename B, typename = void>
4011struct is_comparable : std::false_type {};
4012
4013template<typename Compare, typename A, typename B>
4014struct is_comparable<Compare, A, B, void_t<
4015decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4016decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4017>> : std::true_type {};
4018
4019template<typename T>
4020using detect_is_transparent = typename T::is_transparent;
4021
4022// type trait to check if KeyType can be used as object key (without a BasicJsonType)
4023// see is_usable_as_basic_json_key_type below
4024template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4025 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4026using is_usable_as_key_type = typename std::conditional <
4028 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4029 ObjectKeyType>::value)
4030 && (!RequireTransparentComparator
4031 || is_detected <detect_is_transparent, Comparator>::value)
4033 std::true_type,
4034 std::false_type >::type;
4035
4036// type trait to check if KeyType can be used as object key
4037// true if:
4038// - KeyType is comparable with BasicJsonType::object_t::key_type
4039// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4040// - the comparator is transparent or RequireTransparentComparator is false
4041// - KeyType is not a JSON iterator or json_pointer
4042template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4043 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4044using is_usable_as_basic_json_key_type = typename std::conditional <
4045 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4046 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4047 RequireTransparentComparator, ExcludeObjectKeyType>::value
4049 std::true_type,
4050 std::false_type >::type;
4051
4052template<typename ObjectType, typename KeyType>
4053using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4054
4055// type trait to check if object_t has an erase() member functions accepting KeyType
4056template<typename BasicJsonType, typename KeyType>
4057using has_erase_with_key_type = typename std::conditional <
4058 is_detected <
4060 typename BasicJsonType::object_t, KeyType >::value,
4061 std::true_type,
4062 std::false_type >::type;
4063
4064// a naive helper to check if a type is an ordered_map (exploits the fact that
4065// ordered_map inherits capacity() from std::vector)
4066template <typename T>
4068{
4069 using one = char;
4070
4071 struct two
4072 {
4073 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4074 };
4075
4076 template <typename C> static one test( decltype(&C::capacity) ) ;
4077 template <typename C> static two test(...);
4078
4079 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4080};
4081
4082// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4083template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4085{
4086 return static_cast<T>(value);
4087}
4088
4089template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4091{
4092 return value;
4093}
4094
4095template<typename... Types>
4097
4098template<typename... Types>
4100
4101template<typename... Types>
4103
4104// there's a disjunction trait in another PR; replace when merged
4105template<typename... Types>
4106using same_sign = std::integral_constant < bool,
4107 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4108
4109template<typename OfType, typename T>
4110using never_out_of_range = std::integral_constant < bool,
4111 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4112 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4113
4114template<typename OfType, typename T,
4115 bool OfTypeSigned = std::is_signed<OfType>::value,
4116 bool TSigned = std::is_signed<T>::value>
4118
4119template<typename OfType, typename T>
4120struct value_in_range_of_impl2<OfType, T, false, false>
4121{
4122 static constexpr bool test(T val)
4123 {
4124 using CommonType = typename std::common_type<OfType, T>::type;
4125 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4126 }
4127};
4128
4129template<typename OfType, typename T>
4130struct value_in_range_of_impl2<OfType, T, true, false>
4131{
4132 static constexpr bool test(T val)
4133 {
4134 using CommonType = typename std::common_type<OfType, T>::type;
4135 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4136 }
4137};
4138
4139template<typename OfType, typename T>
4140struct value_in_range_of_impl2<OfType, T, false, true>
4141{
4142 static constexpr bool test(T val)
4143 {
4144 using CommonType = typename std::common_type<OfType, T>::type;
4145 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4146 }
4147};
4148
4149template<typename OfType, typename T>
4150struct value_in_range_of_impl2<OfType, T, true, true>
4151{
4152 static constexpr bool test(T val)
4153 {
4154 using CommonType = typename std::common_type<OfType, T>::type;
4155 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4156 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4157 }
4158};
4159
4160template<typename OfType, typename T,
4161 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4164
4165template<typename OfType, typename T>
4166struct value_in_range_of_impl1<OfType, T, false>
4167{
4168 static constexpr bool test(T val)
4169 {
4171 }
4172};
4173
4174template<typename OfType, typename T>
4175struct value_in_range_of_impl1<OfType, T, true>
4176{
4177 static constexpr bool test(T /*val*/)
4178 {
4179 return true;
4180 }
4181};
4182
4183template<typename OfType, typename T>
4184constexpr bool value_in_range_of(T val)
4185{
4187}
4188
4189template<bool Value>
4190using bool_constant = std::integral_constant<bool, Value>;
4191
4193// is_c_string
4195
4196namespace impl
4197{
4198
4199template<typename T>
4200constexpr bool is_c_string()
4201{
4202 using TUnExt = typename std::remove_extent<T>::type;
4203 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4204 using TUnPtr = typename std::remove_pointer<T>::type;
4205 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4206 return
4207 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4208 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4209}
4210
4211} // namespace impl
4212
4213// checks whether T is a [cv] char */[cv] char[] C string
4214template<typename T>
4215struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4216
4217template<typename T>
4219
4221// is_transparent
4223
4224namespace impl
4225{
4226
4227template<typename T>
4228constexpr bool is_transparent()
4229{
4231}
4232
4233} // namespace impl
4234
4235// checks whether T has a member named is_transparent
4236template<typename T>
4237struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4238
4240
4241} // namespace detail
4243
4244// #include <nlohmann/detail/string_concat.hpp>
4245// __ _____ _____ _____
4246// __| | __| | | | JSON for Modern C++
4247// | | |__ | | | | | | version 3.11.3
4248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4249//
4250// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
4251// SPDX-License-Identifier: MIT
4252
4253
4254
4255#include <cstring> // strlen
4256#include <string> // string
4257#include <utility> // forward
4258
4259// #include <nlohmann/detail/meta/cpp_future.hpp>
4260
4261// #include <nlohmann/detail/meta/detected.hpp>
4262
4263
4265namespace detail
4266{
4267
4268inline std::size_t concat_length()
4269{
4270 return 0;
4271}
4272
4273template<typename... Args>
4274inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4275
4276template<typename StringType, typename... Args>
4277inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4278
4279template<typename... Args>
4280inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4281{
4282 return 1 + concat_length(rest...);
4283}
4284
4285template<typename... Args>
4286inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4287{
4288 // cppcheck-suppress ignoredReturnValue
4289 return ::strlen(cstr) + concat_length(rest...);
4290}
4291
4292template<typename StringType, typename... Args>
4293inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4294{
4295 return str.size() + concat_length(rest...);
4296}
4297
4298template<typename OutStringType>
4299inline void concat_into(OutStringType& /*out*/)
4300{}
4301
4302template<typename StringType, typename Arg>
4303using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4304
4305template<typename StringType, typename Arg>
4307
4308template<typename StringType, typename Arg>
4309using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4310
4311template<typename StringType, typename Arg>
4313
4314template<typename StringType, typename Arg>
4315using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4316
4317template<typename StringType, typename Arg>
4319
4320template<typename StringType, typename Arg>
4321using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4322
4323template<typename StringType, typename Arg>
4325
4326template < typename OutStringType, typename Arg, typename... Args,
4327 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4329inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4330
4331template < typename OutStringType, typename Arg, typename... Args,
4332 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4335inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4336
4337template < typename OutStringType, typename Arg, typename... Args,
4338 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4342inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4343
4344template<typename OutStringType, typename Arg, typename... Args,
4346inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4347{
4348 out.append(std::forward<Arg>(arg));
4349 concat_into(out, std::forward<Args>(rest)...);
4350}
4351
4352template < typename OutStringType, typename Arg, typename... Args,
4353 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4354 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4355inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4356{
4357 out += std::forward<Arg>(arg);
4358 concat_into(out, std::forward<Args>(rest)...);
4359}
4360
4361template < typename OutStringType, typename Arg, typename... Args,
4362 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4363 && !detect_string_can_append_op<OutStringType, Arg>::value
4364 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4365inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4366{
4367 out.append(arg.begin(), arg.end());
4368 concat_into(out, std::forward<Args>(rest)...);
4369}
4370
4371template < typename OutStringType, typename Arg, typename... Args,
4372 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4373 && !detect_string_can_append_op<OutStringType, Arg>::value
4374 && !detect_string_can_append_iter<OutStringType, Arg>::value
4375 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4376inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4377{
4378 out.append(arg.data(), arg.size());
4379 concat_into(out, std::forward<Args>(rest)...);
4380}
4381
4382template<typename OutStringType = std::string, typename... Args>
4383inline OutStringType concat(Args && ... args)
4384{
4385 OutStringType str;
4386 str.reserve(concat_length(args...));
4387 concat_into(str, std::forward<Args>(args)...);
4388 return str;
4389}
4390
4391} // namespace detail
4393
4394
4395// With -Wweak-vtables, Clang will complain about the exception classes as they
4396// have no out-of-line virtual method definitions and their vtable will be
4397// emitted in every translation unit. This issue cannot be fixed with a
4398// header-only library as there is no implementation file to move these
4399// functions to. As a result, we suppress this warning here to avoid client
4400// code to stumble over this. See https://github.com/nlohmann/json/issues/4087
4401// for a discussion.
4402#if defined(__clang__)
4403 #pragma clang diagnostic push
4404 #pragma clang diagnostic ignored "-Wweak-vtables"
4405#endif
4406
4408namespace detail
4409{
4410
4412// exceptions //
4414
4417class exception : public std::exception
4418{
4419 public:
4421 const char* what() const noexcept override
4422 {
4423 return m.what();
4424 }
4425
4427 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4428
4429 protected:
4431 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4432
4433 static std::string name(const std::string& ename, int id_)
4434 {
4435 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4436 }
4437
4438 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4439 {
4440 return "";
4441 }
4442
4443 template<typename BasicJsonType>
4444 static std::string diagnostics(const BasicJsonType* leaf_element)
4445 {
4446#if JSON_DIAGNOSTICS
4447 std::vector<std::string> tokens;
4448 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4449 {
4450 switch (current->m_parent->type())
4451 {
4452 case value_t::array:
4453 {
4454 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4455 {
4456 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4457 {
4458 tokens.emplace_back(std::to_string(i));
4459 break;
4460 }
4461 }
4462 break;
4463 }
4464
4465 case value_t::object:
4466 {
4467 for (const auto& element : *current->m_parent->m_data.m_value.object)
4468 {
4469 if (&element.second == current)
4470 {
4471 tokens.emplace_back(element.first.c_str());
4472 break;
4473 }
4474 }
4475 break;
4476 }
4477
4478 case value_t::null: // LCOV_EXCL_LINE
4479 case value_t::string: // LCOV_EXCL_LINE
4480 case value_t::boolean: // LCOV_EXCL_LINE
4481 case value_t::number_integer: // LCOV_EXCL_LINE
4482 case value_t::number_unsigned: // LCOV_EXCL_LINE
4483 case value_t::number_float: // LCOV_EXCL_LINE
4484 case value_t::binary: // LCOV_EXCL_LINE
4485 case value_t::discarded: // LCOV_EXCL_LINE
4486 default: // LCOV_EXCL_LINE
4487 break; // LCOV_EXCL_LINE
4488 }
4489 }
4490
4491 if (tokens.empty())
4492 {
4493 return "";
4494 }
4495
4496 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4497 [](const std::string & a, const std::string & b)
4498 {
4499 return concat(a, '/', detail::escape(b));
4500 });
4501 return concat('(', str, ") ");
4502#else
4503 static_cast<void>(leaf_element);
4504 return "";
4505#endif
4506 }
4507
4508 private:
4510 std::runtime_error m;
4511};
4512
4516{
4517 public:
4527 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4528 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4529 {
4530 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4531 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4532 return {id_, pos.chars_read_total, w.c_str()};
4533 }
4534
4535 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4536 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4537 {
4538 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4539 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4540 ": ", exception::diagnostics(context), what_arg);
4541 return {id_, byte_, w.c_str()};
4542 }
4543
4553 const std::size_t byte;
4554
4555 private:
4556 parse_error(int id_, std::size_t byte_, const char* what_arg)
4557 : exception(id_, what_arg), byte(byte_) {}
4558
4559 static std::string position_string(const position_t& pos)
4560 {
4561 return concat(" at line ", std::to_string(pos.lines_read + 1),
4562 ", column ", std::to_string(pos.chars_read_current_line));
4563 }
4564};
4565
4569{
4570 public:
4571 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4572 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4573 {
4574 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4575 return {id_, w.c_str()};
4576 }
4577
4578 private:
4580 invalid_iterator(int id_, const char* what_arg)
4581 : exception(id_, what_arg) {}
4582};
4583
4586class type_error : public exception
4587{
4588 public:
4589 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4590 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4591 {
4592 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4593 return {id_, w.c_str()};
4594 }
4595
4596 private:
4598 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4599};
4600
4604{
4605 public:
4606 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4607 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4608 {
4609 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4610 return {id_, w.c_str()};
4611 }
4612
4613 private:
4615 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4616};
4617
4621{
4622 public:
4623 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4624 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4625 {
4626 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4627 return {id_, w.c_str()};
4628 }
4629
4630 private:
4632 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4633};
4634
4635} // namespace detail
4637
4638#if defined(__clang__)
4639 #pragma clang diagnostic pop
4640#endif
4641
4642// #include <nlohmann/detail/macro_scope.hpp>
4643
4644// #include <nlohmann/detail/meta/cpp_future.hpp>
4645
4646// #include <nlohmann/detail/meta/identity_tag.hpp>
4647// __ _____ _____ _____
4648// __| | __| | | | JSON for Modern C++
4649// | | |__ | | | | | | version 3.11.3
4650// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4651//
4652// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
4653// SPDX-License-Identifier: MIT
4654
4655
4656
4657// #include <nlohmann/detail/abi_macros.hpp>
4658
4659
4661namespace detail
4662{
4663
4664// dispatching helper struct
4665template <class T> struct identity_tag {};
4666
4667} // namespace detail
4669
4670// #include <nlohmann/detail/meta/std_fs.hpp>
4671// __ _____ _____ _____
4672// __| | __| | | | JSON for Modern C++
4673// | | |__ | | | | | | version 3.11.3
4674// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4675//
4676// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
4677// SPDX-License-Identifier: MIT
4678
4679
4680
4681// #include <nlohmann/detail/macro_scope.hpp>
4682
4683
4684#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4685#include <experimental/filesystem>
4687namespace detail
4688{
4689namespace std_fs = std::experimental::filesystem;
4690} // namespace detail
4692#elif JSON_HAS_FILESYSTEM
4693#include <filesystem> // NOLINT(build/c++17)
4695namespace detail
4696{
4697namespace std_fs = std::filesystem;
4698} // namespace detail
4700#endif
4701
4702// #include <nlohmann/detail/meta/type_traits.hpp>
4703
4704// #include <nlohmann/detail/string_concat.hpp>
4705
4706// #include <nlohmann/detail/value_t.hpp>
4707
4708
4710namespace detail
4711{
4712
4713template<typename BasicJsonType>
4714inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4715{
4716 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4717 {
4718 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4719 }
4720 n = nullptr;
4721}
4722
4723#ifdef JSON_HAS_CPP_17
4724#ifndef JSON_USE_IMPLICIT_CONVERSIONS
4725template<typename BasicJsonType, typename T>
4726void from_json(const BasicJsonType& j, std::optional<T>& opt)
4727{
4728 if (j.is_null())
4729 {
4730 opt = std::nullopt;
4731 }
4732 else
4733 {
4734 opt.emplace(j.template get<T>());
4735 }
4736}
4737
4738#endif // JSON_USE_IMPLICIT_CONVERSIONS
4739#endif // JSON_HAS_CPP_17
4740
4741// overloads for basic_json template parameters
4742template < typename BasicJsonType, typename ArithmeticType,
4743 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4744 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4745 int > = 0 >
4746void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4747{
4748 switch (static_cast<value_t>(j))
4749 {
4751 {
4752 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4753 break;
4754 }
4756 {
4757 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4758 break;
4759 }
4761 {
4762 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4763 break;
4764 }
4765
4766 case value_t::null:
4767 case value_t::object:
4768 case value_t::array:
4769 case value_t::string:
4770 case value_t::boolean:
4771 case value_t::binary:
4772 case value_t::discarded:
4773 default:
4774 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4775 }
4776}
4777
4778template<typename BasicJsonType>
4779inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4780{
4781 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4782 {
4783 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4784 }
4785 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4786}
4787
4788template<typename BasicJsonType>
4789inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4790{
4791 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4792 {
4793 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4794 }
4795 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4796}
4797
4798template <
4799 typename BasicJsonType, typename StringType,
4800 enable_if_t <
4801 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4802 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4803 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4804 && !is_json_ref<StringType>::value, int > = 0 >
4805inline void from_json(const BasicJsonType& j, StringType& s)
4806{
4807 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4808 {
4809 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4810 }
4811
4812 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4813}
4814
4815template<typename BasicJsonType>
4816inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4817{
4818 get_arithmetic_value(j, val);
4819}
4820
4821template<typename BasicJsonType>
4822inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4823{
4824 get_arithmetic_value(j, val);
4825}
4826
4827template<typename BasicJsonType>
4828inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4829{
4830 get_arithmetic_value(j, val);
4831}
4832
4833#if !JSON_DISABLE_ENUM_SERIALIZATION
4834template<typename BasicJsonType, typename EnumType,
4835 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4836inline void from_json(const BasicJsonType& j, EnumType& e)
4837{
4838 typename std::underlying_type<EnumType>::type val;
4839 get_arithmetic_value(j, val);
4840 e = static_cast<EnumType>(val);
4841}
4842#endif // JSON_DISABLE_ENUM_SERIALIZATION
4843
4844// forward_list doesn't have an insert method
4845template<typename BasicJsonType, typename T, typename Allocator,
4846 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4847inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4848{
4849 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4850 {
4851 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4852 }
4853 l.clear();
4854 std::transform(j.rbegin(), j.rend(),
4855 std::front_inserter(l), [](const BasicJsonType & i)
4856 {
4857 return i.template get<T>();
4858 });
4859}
4860
4861// valarray doesn't have an insert method
4862template<typename BasicJsonType, typename T,
4863 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4864inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4865{
4866 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4867 {
4868 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4869 }
4870 l.resize(j.size());
4871 std::transform(j.begin(), j.end(), std::begin(l),
4872 [](const BasicJsonType & elem)
4873 {
4874 return elem.template get<T>();
4875 });
4876}
4877
4878template<typename BasicJsonType, typename T, std::size_t N>
4879auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4880-> decltype(j.template get<T>(), void())
4881{
4882 for (std::size_t i = 0; i < N; ++i)
4883 {
4884 arr[i] = j.at(i).template get<T>();
4885 }
4886}
4887
4888template<typename BasicJsonType>
4889inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4890{
4891 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4892}
4893
4894template<typename BasicJsonType, typename T, std::size_t N>
4895auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4896 priority_tag<2> /*unused*/)
4897-> decltype(j.template get<T>(), void())
4898{
4899 for (std::size_t i = 0; i < N; ++i)
4900 {
4901 arr[i] = j.at(i).template get<T>();
4902 }
4903}
4904
4905template<typename BasicJsonType, typename ConstructibleArrayType,
4907 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4908 int> = 0>
4909auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4910-> decltype(
4911 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4912 j.template get<typename ConstructibleArrayType::value_type>(),
4913 void())
4914{
4915 using std::end;
4916
4917 ConstructibleArrayType ret;
4918 ret.reserve(j.size());
4919 std::transform(j.begin(), j.end(),
4920 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4921 {
4922 // get<BasicJsonType>() returns *this, this won't call a from_json
4923 // method when value_type is BasicJsonType
4924 return i.template get<typename ConstructibleArrayType::value_type>();
4925 });
4926 arr = std::move(ret);
4927}
4928
4929template<typename BasicJsonType, typename ConstructibleArrayType,
4931 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4932 int> = 0>
4933inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4934 priority_tag<0> /*unused*/)
4935{
4936 using std::end;
4937
4938 ConstructibleArrayType ret;
4939 std::transform(
4940 j.begin(), j.end(), std::inserter(ret, end(ret)),
4941 [](const BasicJsonType & i)
4942 {
4943 // get<BasicJsonType>() returns *this, this won't call a from_json
4944 // method when value_type is BasicJsonType
4945 return i.template get<typename ConstructibleArrayType::value_type>();
4946 });
4947 arr = std::move(ret);
4948}
4949
4950template < typename BasicJsonType, typename ConstructibleArrayType,
4951 enable_if_t <
4952 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4953 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4955 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4956 !is_basic_json<ConstructibleArrayType>::value,
4957 int > = 0 >
4958auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4959-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4960j.template get<typename ConstructibleArrayType::value_type>(),
4961void())
4962{
4963 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4964 {
4965 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4966 }
4967
4968 from_json_array_impl(j, arr, priority_tag<3> {});
4969}
4970
4971template < typename BasicJsonType, typename T, std::size_t... Idx >
4972std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4973 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4974{
4975 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4976}
4977
4978template < typename BasicJsonType, typename T, std::size_t N >
4979auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4980-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4981{
4982 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4983 {
4984 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4985 }
4986
4987 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4988}
4989
4990template<typename BasicJsonType>
4991inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4992{
4993 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4994 {
4995 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4996 }
4997
4998 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4999}
5000
5001template<typename BasicJsonType, typename ConstructibleObjectType,
5002 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5003inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5004{
5005 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5006 {
5007 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5008 }
5009
5010 ConstructibleObjectType ret;
5011 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5012 using value_type = typename ConstructibleObjectType::value_type;
5013 std::transform(
5014 inner_object->begin(), inner_object->end(),
5015 std::inserter(ret, ret.begin()),
5016 [](typename BasicJsonType::object_t::value_type const & p)
5017 {
5018 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5019 });
5020 obj = std::move(ret);
5021}
5022
5023// overload for arithmetic types, not chosen for basic_json template arguments
5024// (BooleanType, etc..); note: Is it really necessary to provide explicit
5025// overloads for boolean_t etc. in case of a custom BooleanType which is not
5026// an arithmetic type?
5027template < typename BasicJsonType, typename ArithmeticType,
5028 enable_if_t <
5029 std::is_arithmetic<ArithmeticType>::value&&
5030 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5031 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5032 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5033 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5034 int > = 0 >
5035inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5036{
5037 switch (static_cast<value_t>(j))
5038 {
5040 {
5041 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5042 break;
5043 }
5045 {
5046 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5047 break;
5048 }
5050 {
5051 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5052 break;
5053 }
5054 case value_t::boolean:
5055 {
5056 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5057 break;
5058 }
5059
5060 case value_t::null:
5061 case value_t::object:
5062 case value_t::array:
5063 case value_t::string:
5064 case value_t::binary:
5065 case value_t::discarded:
5066 default:
5067 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5068 }
5069}
5070
5071template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5072std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5073{
5074 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5075}
5076
5077template < typename BasicJsonType, class A1, class A2 >
5078std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5079{
5080 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5081 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5082}
5083
5084template<typename BasicJsonType, typename A1, typename A2>
5085inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5086{
5087 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5088}
5089
5090template<typename BasicJsonType, typename... Args>
5091std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5092{
5093 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5094}
5095
5096template<typename BasicJsonType, typename... Args>
5097inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5098{
5099 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5100}
5101
5102template<typename BasicJsonType, typename TupleRelated>
5103auto from_json(BasicJsonType&& j, TupleRelated&& t)
5104-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5105{
5106 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5107 {
5108 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5109 }
5110
5111 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5112}
5113
5114template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5115 typename = enable_if_t < !std::is_constructible <
5116 typename BasicJsonType::string_t, Key >::value >>
5117inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5118{
5119 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5120 {
5121 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5122 }
5123 m.clear();
5124 for (const auto& p : j)
5125 {
5126 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5127 {
5128 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5129 }
5130 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5131 }
5132}
5133
5134template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5135 typename = enable_if_t < !std::is_constructible <
5136 typename BasicJsonType::string_t, Key >::value >>
5137inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5138{
5139 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5140 {
5141 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5142 }
5143 m.clear();
5144 for (const auto& p : j)
5145 {
5146 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5147 {
5148 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5149 }
5150 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5151 }
5152}
5153
5154#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5155template<typename BasicJsonType>
5156inline void from_json(const BasicJsonType& j, std_fs::path& p)
5157{
5158 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5159 {
5160 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5161 }
5162 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5163}
5164#endif
5165
5166struct from_json_fn
5167{
5168 template<typename BasicJsonType, typename T>
5169 auto operator()(const BasicJsonType& j, T&& val) const
5170 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5171 -> decltype(from_json(j, std::forward<T>(val)))
5172 {
5173 return from_json(j, std::forward<T>(val));
5174 }
5175};
5176
5177} // namespace detail
5178
5179#ifndef JSON_HAS_CPP_17
5183namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5184{
5185#endif
5186JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5188#ifndef JSON_HAS_CPP_17
5189} // namespace
5190#endif
5191
5193
5194// #include <nlohmann/detail/conversions/to_json.hpp>
5195// __ _____ _____ _____
5196// __| | __| | | | JSON for Modern C++
5197// | | |__ | | | | | | version 3.11.3
5198// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5199//
5200// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
5201// SPDX-License-Identifier: MIT
5202
5203
5204
5205#include <algorithm> // copy
5206#include <iterator> // begin, end
5207#ifdef JSON_HAS_CPP_17
5208 #include <optional> // optional
5209#endif
5210#include <string> // string
5211#include <tuple> // tuple, get
5212#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5213#include <utility> // move, forward, declval, pair
5214#include <valarray> // valarray
5215#include <vector> // vector
5216
5217// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5218// __ _____ _____ _____
5219// __| | __| | | | JSON for Modern C++
5220// | | |__ | | | | | | version 3.11.3
5221// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5222//
5223// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
5224// SPDX-License-Identifier: MIT
5225
5226
5227
5228#include <cstddef> // size_t
5229#include <iterator> // forward_iterator_tag
5230#include <string> // string, to_string
5231#include <tuple> // tuple_size, get, tuple_element
5232#include <utility> // move
5233
5234#if JSON_HAS_RANGES
5235 #include <ranges> // enable_borrowed_range
5236#endif
5237
5238// #include <nlohmann/detail/abi_macros.hpp>
5239
5240// #include <nlohmann/detail/meta/type_traits.hpp>
5241
5242// #include <nlohmann/detail/value_t.hpp>
5243
5244
5246namespace detail
5247{
5248
5249template<typename string_type>
5250void int_to_string( string_type& target, std::size_t value )
5251{
5252 // For ADL
5253 using std::to_string;
5254 target = to_string(value);
5255}
5256template<typename IteratorType> class iteration_proxy_value
5257{
5258 public:
5259 using difference_type = std::ptrdiff_t;
5263 using iterator_category = std::forward_iterator_tag;
5264 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5265
5266 private:
5268 IteratorType anchor{};
5270 std::size_t array_index = 0;
5272 mutable std::size_t array_index_last = 0;
5274 mutable string_type array_index_str = "0";
5276 string_type empty_str{};
5277
5278 public:
5279 explicit iteration_proxy_value() = default;
5280 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5281 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5282 && std::is_nothrow_default_constructible<string_type>::value)
5283 : anchor(std::move(it))
5284 , array_index(array_index_)
5285 {}
5286
5289 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5291 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5292 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5294 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5295 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5297
5299 const iteration_proxy_value& operator*() const
5300 {
5301 return *this;
5302 }
5303
5306 {
5307 ++anchor;
5308 ++array_index;
5309
5310 return *this;
5311 }
5312
5313 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5314 {
5315 auto tmp = iteration_proxy_value(anchor, array_index);
5316 ++anchor;
5317 ++array_index;
5318 return tmp;
5319 }
5320
5323 {
5324 return anchor == o.anchor;
5325 }
5326
5329 {
5330 return anchor != o.anchor;
5331 }
5332
5334 const string_type& key() const
5335 {
5336 JSON_ASSERT(anchor.m_object != nullptr);
5337
5338 switch (anchor.m_object->type())
5339 {
5340 // use integer array index as key
5341 case value_t::array:
5342 {
5343 if (array_index != array_index_last)
5344 {
5345 int_to_string( array_index_str, array_index );
5346 array_index_last = array_index;
5347 }
5348 return array_index_str;
5349 }
5350
5351 // use key from the object
5352 case value_t::object:
5353 return anchor.key();
5354
5355 // use an empty key for all primitive types
5356 case value_t::null:
5357 case value_t::string:
5358 case value_t::boolean:
5362 case value_t::binary:
5363 case value_t::discarded:
5364 default:
5365 return empty_str;
5366 }
5367 }
5368
5370 typename IteratorType::reference value() const
5371 {
5372 return anchor.value();
5373 }
5374};
5375
5377template<typename IteratorType> class iteration_proxy
5378{
5379 private:
5381 typename IteratorType::pointer container = nullptr;
5382
5383 public:
5384 explicit iteration_proxy() = default;
5385
5387 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5388 : container(&cont) {}
5389
5392 iteration_proxy(iteration_proxy&&) noexcept = default;
5393 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5394 ~iteration_proxy() = default;
5395
5397 iteration_proxy_value<IteratorType> begin() const noexcept
5398 {
5399 return iteration_proxy_value<IteratorType>(container->begin());
5400 }
5401
5404 {
5405 return iteration_proxy_value<IteratorType>(container->end());
5406 }
5407};
5408
5409// Structured Bindings Support
5410// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5411// And see https://github.com/nlohmann/json/pull/1391
5412template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5413auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5414{
5415 return i.key();
5416}
5417// Structured Bindings Support
5418// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5419// And see https://github.com/nlohmann/json/pull/1391
5420template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5421auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5422{
5423 return i.value();
5424}
5425
5426} // namespace detail
5428
5429// The Addition to the STD Namespace is required to add
5430// Structured Bindings Support to the iteration_proxy_value class
5431// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5432// And see https://github.com/nlohmann/json/pull/1391
5433namespace std
5434{
5435
5436#if defined(__clang__)
5437 // Fix: https://github.com/nlohmann/json/issues/1401
5438 #pragma clang diagnostic push
5439 #pragma clang diagnostic ignored "-Wmismatched-tags"
5440#endif
5441template<typename IteratorType>
5442class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5443 : public std::integral_constant<std::size_t, 2> {};
5444
5445template<std::size_t N, typename IteratorType>
5446class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5447{
5448 public:
5449 using type = decltype(
5450 get<N>(std::declval <
5451 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5452};
5453#if defined(__clang__)
5454 #pragma clang diagnostic pop
5455#endif
5456
5457} // namespace std
5458
5459#if JSON_HAS_RANGES
5460 template <typename IteratorType>
5461 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5462#endif
5463
5464// #include <nlohmann/detail/macro_scope.hpp>
5465
5466// #include <nlohmann/detail/meta/cpp_future.hpp>
5467
5468// #include <nlohmann/detail/meta/std_fs.hpp>
5469
5470// #include <nlohmann/detail/meta/type_traits.hpp>
5471
5472// #include <nlohmann/detail/value_t.hpp>
5473
5474
5476namespace detail
5477{
5478
5480// constructors //
5482
5483/*
5484 * Note all external_constructor<>::construct functions need to call
5485 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5486 * allocated value (e.g., a string). See bug issue
5487 * https://github.com/nlohmann/json/issues/2865 for more information.
5488 */
5489
5490template<value_t> struct external_constructor;
5491
5492template<>
5494{
5495 template<typename BasicJsonType>
5496 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5497 {
5498 j.m_data.m_value.destroy(j.m_data.m_type);
5499 j.m_data.m_type = value_t::boolean;
5500 j.m_data.m_value = b;
5501 j.assert_invariant();
5502 }
5503};
5504
5505template<>
5507{
5508 template<typename BasicJsonType>
5509 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5510 {
5511 j.m_data.m_value.destroy(j.m_data.m_type);
5512 j.m_data.m_type = value_t::string;
5513 j.m_data.m_value = s;
5514 j.assert_invariant();
5515 }
5516
5517 template<typename BasicJsonType>
5518 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5519 {
5520 j.m_data.m_value.destroy(j.m_data.m_type);
5521 j.m_data.m_type = value_t::string;
5522 j.m_data.m_value = std::move(s);
5523 j.assert_invariant();
5524 }
5525
5526 template < typename BasicJsonType, typename CompatibleStringType,
5527 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5528 int > = 0 >
5529 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5530 {
5531 j.m_data.m_value.destroy(j.m_data.m_type);
5532 j.m_data.m_type = value_t::string;
5533 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5534 j.assert_invariant();
5535 }
5536};
5537
5538template<>
5540{
5541 template<typename BasicJsonType>
5542 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5543 {
5544 j.m_data.m_value.destroy(j.m_data.m_type);
5545 j.m_data.m_type = value_t::binary;
5546 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5547 j.assert_invariant();
5548 }
5549
5550 template<typename BasicJsonType>
5551 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5552 {
5553 j.m_data.m_value.destroy(j.m_data.m_type);
5554 j.m_data.m_type = value_t::binary;
5555 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5556 j.assert_invariant();
5557 }
5558};
5559
5560template<>
5562{
5563 template<typename BasicJsonType>
5564 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5565 {
5566 j.m_data.m_value.destroy(j.m_data.m_type);
5567 j.m_data.m_type = value_t::number_float;
5568 j.m_data.m_value = val;
5569 j.assert_invariant();
5570 }
5571};
5572
5573template<>
5575{
5576 template<typename BasicJsonType>
5577 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5578 {
5579 j.m_data.m_value.destroy(j.m_data.m_type);
5580 j.m_data.m_type = value_t::number_unsigned;
5581 j.m_data.m_value = val;
5582 j.assert_invariant();
5583 }
5584};
5585
5586template<>
5588{
5589 template<typename BasicJsonType>
5590 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5591 {
5592 j.m_data.m_value.destroy(j.m_data.m_type);
5593 j.m_data.m_type = value_t::number_integer;
5594 j.m_data.m_value = val;
5595 j.assert_invariant();
5596 }
5597};
5598
5599template<>
5601{
5602 template<typename BasicJsonType>
5603 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5604 {
5605 j.m_data.m_value.destroy(j.m_data.m_type);
5606 j.m_data.m_type = value_t::array;
5607 j.m_data.m_value = arr;
5608 j.set_parents();
5609 j.assert_invariant();
5610 }
5611
5612 template<typename BasicJsonType>
5613 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5614 {
5615 j.m_data.m_value.destroy(j.m_data.m_type);
5616 j.m_data.m_type = value_t::array;
5617 j.m_data.m_value = std::move(arr);
5618 j.set_parents();
5619 j.assert_invariant();
5620 }
5621
5622 template < typename BasicJsonType, typename CompatibleArrayType,
5623 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5624 int > = 0 >
5625 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5626 {
5627 using std::begin;
5628 using std::end;
5629
5630 j.m_data.m_value.destroy(j.m_data.m_type);
5631 j.m_data.m_type = value_t::array;
5632 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5633 j.set_parents();
5634 j.assert_invariant();
5635 }
5636
5637 template<typename BasicJsonType>
5638 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5639 {
5640 j.m_data.m_value.destroy(j.m_data.m_type);
5641 j.m_data.m_type = value_t::array;
5642 j.m_data.m_value = value_t::array;
5643 j.m_data.m_value.array->reserve(arr.size());
5644 for (const bool x : arr)
5645 {
5646 j.m_data.m_value.array->push_back(x);
5647 j.set_parent(j.m_data.m_value.array->back());
5648 }
5649 j.assert_invariant();
5650 }
5651
5652 template<typename BasicJsonType, typename T,
5654 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5655 {
5656 j.m_data.m_value.destroy(j.m_data.m_type);
5657 j.m_data.m_type = value_t::array;
5658 j.m_data.m_value = value_t::array;
5659 j.m_data.m_value.array->resize(arr.size());
5660 if (arr.size() > 0)
5661 {
5662 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5663 }
5664 j.set_parents();
5665 j.assert_invariant();
5666 }
5667};
5668
5669template<>
5671{
5672 template<typename BasicJsonType>
5673 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5674 {
5675 j.m_data.m_value.destroy(j.m_data.m_type);
5676 j.m_data.m_type = value_t::object;
5677 j.m_data.m_value = obj;
5678 j.set_parents();
5679 j.assert_invariant();
5680 }
5681
5682 template<typename BasicJsonType>
5683 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5684 {
5685 j.m_data.m_value.destroy(j.m_data.m_type);
5686 j.m_data.m_type = value_t::object;
5687 j.m_data.m_value = std::move(obj);
5688 j.set_parents();
5689 j.assert_invariant();
5690 }
5691
5692 template < typename BasicJsonType, typename CompatibleObjectType,
5693 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5694 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5695 {
5696 using std::begin;
5697 using std::end;
5698
5699 j.m_data.m_value.destroy(j.m_data.m_type);
5700 j.m_data.m_type = value_t::object;
5701 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5702 j.set_parents();
5703 j.assert_invariant();
5704 }
5705};
5706
5708// to_json //
5710
5711#ifdef JSON_HAS_CPP_17
5712template<typename BasicJsonType, typename T,
5713 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5714void to_json(BasicJsonType& j, const std::optional<T>& opt)
5715{
5716 if (opt.has_value())
5717 {
5718 j = *opt;
5719 }
5720 else
5721 {
5722 j = nullptr;
5723 }
5724}
5725#endif
5726
5727template<typename BasicJsonType, typename T,
5728 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5729inline void to_json(BasicJsonType& j, T b) noexcept
5730{
5732}
5733
5734template < typename BasicJsonType, typename BoolRef,
5735 enable_if_t <
5736 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5737 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5738 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5739 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5740 typename BasicJsonType::boolean_t >::value))
5741 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5742inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5743{
5744 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5745}
5746
5747template<typename BasicJsonType, typename CompatibleString,
5748 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5749inline void to_json(BasicJsonType& j, const CompatibleString& s)
5750{
5752}
5753
5754template<typename BasicJsonType>
5755inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5756{
5758}
5759
5760template<typename BasicJsonType, typename FloatType,
5761 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5762inline void to_json(BasicJsonType& j, FloatType val) noexcept
5763{
5764 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5765}
5766
5767template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5768 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5769inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5770{
5771 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5772}
5773
5774template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5775 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5776inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5777{
5778 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5779}
5780
5781#if !JSON_DISABLE_ENUM_SERIALIZATION
5782template<typename BasicJsonType, typename EnumType,
5783 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5784inline void to_json(BasicJsonType& j, EnumType e) noexcept
5785{
5786 using underlying_type = typename std::underlying_type<EnumType>::type;
5787 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5788 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5789}
5790#endif // JSON_DISABLE_ENUM_SERIALIZATION
5791
5792template<typename BasicJsonType>
5793inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5794{
5796}
5797
5798template < typename BasicJsonType, typename CompatibleArrayType,
5799 enable_if_t < is_compatible_array_type<BasicJsonType,
5800 CompatibleArrayType>::value&&
5801 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5803 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5804 !is_basic_json<CompatibleArrayType>::value,
5805 int > = 0 >
5806inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5807{
5809}
5810
5811template<typename BasicJsonType>
5812inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5813{
5815}
5816
5817template<typename BasicJsonType, typename T,
5818 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5819inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5820{
5822}
5823
5824template<typename BasicJsonType>
5825inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5826{
5828}
5829
5830template < typename BasicJsonType, typename CompatibleObjectType,
5831 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5832inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5833{
5835}
5836
5837template<typename BasicJsonType>
5838inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5839{
5841}
5842
5843template <
5844 typename BasicJsonType, typename T, std::size_t N,
5845 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5846 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5847 int > = 0 >
5848inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5849{
5851}
5852
5853template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5854inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5855{
5856 j = { p.first, p.second };
5857}
5858
5859// for https://github.com/nlohmann/json/pull/1134
5860template<typename BasicJsonType, typename T,
5861 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5862inline void to_json(BasicJsonType& j, const T& b)
5863{
5864 j = { {b.key(), b.value()} };
5865}
5866
5867template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5868inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5869{
5870 j = { std::get<Idx>(t)... };
5871}
5872
5873template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5874inline void to_json(BasicJsonType& j, const T& t)
5875{
5876 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5877}
5878
5879#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5880template<typename BasicJsonType>
5881inline void to_json(BasicJsonType& j, const std_fs::path& p)
5882{
5883 j = p.string();
5884}
5885#endif
5886
5888{
5889 template<typename BasicJsonType, typename T>
5890 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5891 -> decltype(to_json(j, std::forward<T>(val)), void())
5892 {
5893 return to_json(j, std::forward<T>(val));
5894 }
5895};
5896} // namespace detail
5897
5898#ifndef JSON_HAS_CPP_17
5902namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5903{
5904#endif
5905JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5907#ifndef JSON_HAS_CPP_17
5908} // namespace
5909#endif
5910
5912
5913// #include <nlohmann/detail/meta/identity_tag.hpp>
5914
5915
5917
5919template<typename ValueType, typename>
5921{
5924 template<typename BasicJsonType, typename TargetType = ValueType>
5925 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5926 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5927 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5928 {
5929 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5930 }
5931
5934 template<typename BasicJsonType, typename TargetType = ValueType>
5935 static auto from_json(BasicJsonType && j) noexcept(
5936 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5937 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5938 {
5939 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5940 }
5941
5944 template<typename BasicJsonType, typename TargetType = ValueType>
5945 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5946 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5947 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5948 {
5949 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5950 }
5951};
5952
5954
5955// #include <nlohmann/byte_container_with_subtype.hpp>
5956// __ _____ _____ _____
5957// __| | __| | | | JSON for Modern C++
5958// | | |__ | | | | | | version 3.11.3
5959// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5960//
5961// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
5962// SPDX-License-Identifier: MIT
5963
5964
5965
5966#include <cstdint> // uint8_t, uint64_t
5967#include <tuple> // tie
5968#include <utility> // move
5969
5970// #include <nlohmann/detail/abi_macros.hpp>
5971
5972
5974
5977template<typename BinaryType>
5978class byte_container_with_subtype : public BinaryType
5979{
5980 public:
5981 using container_type = BinaryType;
5982 using subtype_type = std::uint64_t;
5983
5986 : container_type()
5987 {}
5988
5991 : container_type(b)
5992 {}
5993
5996 : container_type(std::move(b))
5997 {}
5998
6001 : container_type(b)
6002 , m_subtype(subtype_)
6003 , m_has_subtype(true)
6004 {}
6005
6007 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6008 : container_type(std::move(b))
6009 , m_subtype(subtype_)
6010 , m_has_subtype(true)
6011 {}
6012
6014 {
6015 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6016 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6017 }
6018
6020 {
6021 return !(rhs == *this);
6022 }
6023
6026 void set_subtype(subtype_type subtype_) noexcept
6027 {
6028 m_subtype = subtype_;
6029 m_has_subtype = true;
6030 }
6031
6034 constexpr subtype_type subtype() const noexcept
6035 {
6036 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6037 }
6038
6041 constexpr bool has_subtype() const noexcept
6042 {
6043 return m_has_subtype;
6044 }
6045
6048 void clear_subtype() noexcept
6049 {
6050 m_subtype = 0;
6051 m_has_subtype = false;
6052 }
6053
6054 private:
6055 subtype_type m_subtype = 0;
6056 bool m_has_subtype = false;
6057};
6058
6060
6061// #include <nlohmann/detail/conversions/from_json.hpp>
6062
6063// #include <nlohmann/detail/conversions/to_json.hpp>
6064
6065// #include <nlohmann/detail/exceptions.hpp>
6066
6067// #include <nlohmann/detail/hash.hpp>
6068// __ _____ _____ _____
6069// __| | __| | | | JSON for Modern C++
6070// | | |__ | | | | | | version 3.11.3
6071// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6072//
6073// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6074// SPDX-License-Identifier: MIT
6075
6076
6077
6078#include <cstdint> // uint8_t
6079#include <cstddef> // size_t
6080#include <functional> // hash
6081
6082// #include <nlohmann/detail/abi_macros.hpp>
6083
6084// #include <nlohmann/detail/value_t.hpp>
6085
6086
6088namespace detail
6089{
6090
6091// boost::hash_combine
6092inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6093{
6094 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6095 return seed;
6096}
6097
6109template<typename BasicJsonType>
6110std::size_t hash(const BasicJsonType& j)
6111{
6112 using string_t = typename BasicJsonType::string_t;
6113 using number_integer_t = typename BasicJsonType::number_integer_t;
6114 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6115 using number_float_t = typename BasicJsonType::number_float_t;
6116
6117 const auto type = static_cast<std::size_t>(j.type());
6118 switch (j.type())
6119 {
6120 case BasicJsonType::value_t::null:
6121 case BasicJsonType::value_t::discarded:
6122 {
6123 return combine(type, 0);
6124 }
6125
6126 case BasicJsonType::value_t::object:
6127 {
6128 auto seed = combine(type, j.size());
6129 for (const auto& element : j.items())
6130 {
6131 const auto h = std::hash<string_t> {}(element.key());
6132 seed = combine(seed, h);
6133 seed = combine(seed, hash(element.value()));
6134 }
6135 return seed;
6136 }
6137
6138 case BasicJsonType::value_t::array:
6139 {
6140 auto seed = combine(type, j.size());
6141 for (const auto& element : j)
6142 {
6143 seed = combine(seed, hash(element));
6144 }
6145 return seed;
6146 }
6147
6148 case BasicJsonType::value_t::string:
6149 {
6150 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6151 return combine(type, h);
6152 }
6153
6154 case BasicJsonType::value_t::boolean:
6155 {
6156 const auto h = std::hash<bool> {}(j.template get<bool>());
6157 return combine(type, h);
6158 }
6159
6160 case BasicJsonType::value_t::number_integer:
6161 {
6162 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6163 return combine(type, h);
6164 }
6165
6166 case BasicJsonType::value_t::number_unsigned:
6167 {
6168 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6169 return combine(type, h);
6170 }
6171
6172 case BasicJsonType::value_t::number_float:
6173 {
6174 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6175 return combine(type, h);
6176 }
6177
6178 case BasicJsonType::value_t::binary:
6179 {
6180 auto seed = combine(type, j.get_binary().size());
6181 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6182 seed = combine(seed, h);
6183 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6184 for (const auto byte : j.get_binary())
6185 {
6186 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6187 }
6188 return seed;
6189 }
6190
6191 default: // LCOV_EXCL_LINE
6192 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6193 return 0; // LCOV_EXCL_LINE
6194 }
6195}
6196
6197} // namespace detail
6199
6200// #include <nlohmann/detail/input/binary_reader.hpp>
6201// __ _____ _____ _____
6202// __| | __| | | | JSON for Modern C++
6203// | | |__ | | | | | | version 3.11.3
6204// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6205//
6206// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6207// SPDX-License-Identifier: MIT
6208
6209
6210
6211#include <algorithm> // generate_n
6212#include <array> // array
6213#include <cmath> // ldexp
6214#include <cstddef> // size_t
6215#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6216#include <cstdio> // snprintf
6217#include <cstring> // memcpy
6218#include <iterator> // back_inserter
6219#include <limits> // numeric_limits
6220#include <string> // char_traits, string
6221#include <utility> // make_pair, move
6222#include <vector> // vector
6223#ifdef __cpp_lib_byteswap
6224 #include <bit> //byteswap
6225#endif
6226
6227// #include <nlohmann/detail/exceptions.hpp>
6228
6229// #include <nlohmann/detail/input/input_adapters.hpp>
6230// __ _____ _____ _____
6231// __| | __| | | | JSON for Modern C++
6232// | | |__ | | | | | | version 3.11.3
6233// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6234//
6235// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6236// SPDX-License-Identifier: MIT
6237
6238
6239
6240#include <array> // array
6241#include <cstddef> // size_t
6242#include <cstring> // strlen
6243#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6244#include <memory> // shared_ptr, make_shared, addressof
6245#include <numeric> // accumulate
6246#include <string> // string, char_traits
6247#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6248#include <utility> // pair, declval
6249
6250#ifndef JSON_NO_IO
6251 #include <cstdio> // FILE *
6252 #include <istream> // istream
6253#endif // JSON_NO_IO
6254
6255// #include <nlohmann/detail/exceptions.hpp>
6256
6257// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6258
6259// #include <nlohmann/detail/macro_scope.hpp>
6260
6261// #include <nlohmann/detail/meta/type_traits.hpp>
6262
6263
6265namespace detail
6266{
6267
6269enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6270
6272// input adapters //
6274
6275#ifndef JSON_NO_IO
6280class file_input_adapter
6281{
6282 public:
6283 using char_type = char;
6284
6286 explicit file_input_adapter(std::FILE* f) noexcept
6287 : m_file(f)
6288 {
6289 JSON_ASSERT(m_file != nullptr);
6290 }
6291
6292 // make class move-only
6293 file_input_adapter(const file_input_adapter&) = delete;
6294 file_input_adapter(file_input_adapter&&) noexcept = default;
6295 file_input_adapter& operator=(const file_input_adapter&) = delete;
6296 file_input_adapter& operator=(file_input_adapter&&) = delete;
6297 ~file_input_adapter() = default;
6298
6299 std::char_traits<char>::int_type get_character() noexcept
6300 {
6301 return std::fgetc(m_file);
6302 }
6303
6304 // returns the number of characters successfully read
6305 template<class T>
6306 std::size_t get_elements(T* dest, std::size_t count = 1)
6307 {
6308 return fread(dest, 1, sizeof(T) * count, m_file);
6309 }
6310
6311 private:
6313 std::FILE* m_file;
6314};
6315
6325class input_stream_adapter
6326{
6327 public:
6328 using char_type = char;
6329
6330 ~input_stream_adapter()
6331 {
6332 // clear stream flags; we use underlying streambuf I/O, do not
6333 // maintain ifstream flags, except eof
6334 if (is != nullptr)
6335 {
6336 is->clear(is->rdstate() & std::ios::eofbit);
6337 }
6338 }
6339
6340 explicit input_stream_adapter(std::istream& i)
6341 : is(&i), sb(i.rdbuf())
6342 {}
6343
6344 // delete because of pointer members
6345 input_stream_adapter(const input_stream_adapter&) = delete;
6346 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6347 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6348
6349 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6350 : is(rhs.is), sb(rhs.sb)
6351 {
6352 rhs.is = nullptr;
6353 rhs.sb = nullptr;
6354 }
6355
6356 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6357 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6358 // end up as the same value, e.g. 0xFFFFFFFF.
6359 std::char_traits<char>::int_type get_character()
6360 {
6361 auto res = sb->sbumpc();
6362 // set eof manually, as we don't use the istream interface.
6363 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6364 {
6365 is->clear(is->rdstate() | std::ios::eofbit);
6366 }
6367 return res;
6368 }
6369
6370 template<class T>
6371 std::size_t get_elements(T* dest, std::size_t count = 1)
6372 {
6373 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6374 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6375 {
6376 is->clear(is->rdstate() | std::ios::eofbit);
6377 }
6378 return res;
6379 }
6380
6381 private:
6383 std::istream* is = nullptr;
6384 std::streambuf* sb = nullptr;
6385};
6386#endif // JSON_NO_IO
6387
6388// General-purpose iterator-based adapter. It might not be as fast as
6389// theoretically possible for some containers, but it is extremely versatile.
6390template<typename IteratorType>
6391class iterator_input_adapter
6392{
6393 public:
6394 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6395
6396 iterator_input_adapter(IteratorType first, IteratorType last)
6397 : current(std::move(first)), end(std::move(last))
6398 {}
6399
6400 typename char_traits<char_type>::int_type get_character()
6401 {
6402 if (JSON_HEDLEY_LIKELY(current != end))
6403 {
6404 auto result = char_traits<char_type>::to_int_type(*current);
6405 std::advance(current, 1);
6406 return result;
6407 }
6408
6409 return char_traits<char_type>::eof();
6410 }
6411
6412 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6413 template<class T>
6414 std::size_t get_elements(T* dest, std::size_t count = 1)
6415 {
6416 auto* ptr = reinterpret_cast<char*>(dest);
6417 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6418 {
6419 if (JSON_HEDLEY_LIKELY(current != end))
6420 {
6421 ptr[read_index] = static_cast<char>(*current);
6422 std::advance(current, 1);
6423 }
6424 else
6425 {
6426 return read_index;
6427 }
6428 }
6429 return count * sizeof(T);
6430 }
6431
6432 private:
6433 IteratorType current;
6434 IteratorType end;
6435
6436 template<typename BaseInputAdapter, size_t T>
6437 friend struct wide_string_input_helper;
6438
6439 bool empty() const
6440 {
6441 return current == end;
6442 }
6443};
6444
6445template<typename BaseInputAdapter, size_t T>
6446struct wide_string_input_helper;
6447
6448template<typename BaseInputAdapter>
6449struct wide_string_input_helper<BaseInputAdapter, 4>
6450{
6451 // UTF-32
6452 static void fill_buffer(BaseInputAdapter& input,
6453 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6454 size_t& utf8_bytes_index,
6455 size_t& utf8_bytes_filled)
6456 {
6457 utf8_bytes_index = 0;
6458
6459 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6460 {
6461 utf8_bytes[0] = std::char_traits<char>::eof();
6462 utf8_bytes_filled = 1;
6463 }
6464 else
6465 {
6466 // get the current character
6467 const auto wc = input.get_character();
6468
6469 // UTF-32 to UTF-8 encoding
6470 if (wc < 0x80)
6471 {
6472 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6473 utf8_bytes_filled = 1;
6474 }
6475 else if (wc <= 0x7FF)
6476 {
6477 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6478 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6479 utf8_bytes_filled = 2;
6480 }
6481 else if (wc <= 0xFFFF)
6482 {
6483 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6484 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6485 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6486 utf8_bytes_filled = 3;
6487 }
6488 else if (wc <= 0x10FFFF)
6489 {
6490 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6491 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6492 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6493 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6494 utf8_bytes_filled = 4;
6495 }
6496 else
6497 {
6498 // unknown character
6499 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6500 utf8_bytes_filled = 1;
6501 }
6502 }
6503 }
6504};
6505
6506template<typename BaseInputAdapter>
6507struct wide_string_input_helper<BaseInputAdapter, 2>
6508{
6509 // UTF-16
6510 static void fill_buffer(BaseInputAdapter& input,
6511 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6512 size_t& utf8_bytes_index,
6513 size_t& utf8_bytes_filled)
6514 {
6515 utf8_bytes_index = 0;
6516
6517 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6518 {
6519 utf8_bytes[0] = std::char_traits<char>::eof();
6520 utf8_bytes_filled = 1;
6521 }
6522 else
6523 {
6524 // get the current character
6525 const auto wc = input.get_character();
6526
6527 // UTF-16 to UTF-8 encoding
6528 if (wc < 0x80)
6529 {
6530 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6531 utf8_bytes_filled = 1;
6532 }
6533 else if (wc <= 0x7FF)
6534 {
6535 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6536 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6537 utf8_bytes_filled = 2;
6538 }
6539 else if (0xD800 > wc || wc >= 0xE000)
6540 {
6541 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6542 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6543 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6544 utf8_bytes_filled = 3;
6545 }
6546 else
6547 {
6548 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6549 {
6550 const auto wc2 = static_cast<unsigned int>(input.get_character());
6551 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6552 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6553 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6554 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6555 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6556 utf8_bytes_filled = 4;
6557 }
6558 else
6559 {
6560 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6561 utf8_bytes_filled = 1;
6562 }
6563 }
6564 }
6565 }
6566};
6567
6568// Wraps another input adapter to convert wide character types into individual bytes.
6569template<typename BaseInputAdapter, typename WideCharType>
6570class wide_string_input_adapter
6571{
6572 public:
6573 using char_type = char;
6574
6575 wide_string_input_adapter(BaseInputAdapter base)
6576 : base_adapter(base) {}
6577
6578 typename std::char_traits<char>::int_type get_character() noexcept
6579 {
6580 // check if buffer needs to be filled
6581 if (utf8_bytes_index == utf8_bytes_filled)
6582 {
6583 fill_buffer<sizeof(WideCharType)>();
6584
6585 JSON_ASSERT(utf8_bytes_filled > 0);
6586 JSON_ASSERT(utf8_bytes_index == 0);
6587 }
6588
6589 // use buffer
6590 JSON_ASSERT(utf8_bytes_filled > 0);
6591 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6592 return utf8_bytes[utf8_bytes_index++];
6593 }
6594
6595 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6596 template<class T>
6597 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6598 {
6599 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6600 }
6601
6602 private:
6603 BaseInputAdapter base_adapter;
6604
6605 template<size_t T>
6606 void fill_buffer()
6607 {
6608 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6609 }
6610
6612 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6613
6615 std::size_t utf8_bytes_index = 0;
6617 std::size_t utf8_bytes_filled = 0;
6618};
6619
6620template<typename IteratorType, typename Enable = void>
6621struct iterator_input_adapter_factory
6622{
6623 using iterator_type = IteratorType;
6624 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6625 using adapter_type = iterator_input_adapter<iterator_type>;
6626
6627 static adapter_type create(IteratorType first, IteratorType last)
6628 {
6629 return adapter_type(std::move(first), std::move(last));
6630 }
6631};
6632
6633template<typename T>
6634struct is_iterator_of_multibyte
6635{
6636 using value_type = typename std::iterator_traits<T>::value_type;
6637 enum
6638 {
6639 value = sizeof(value_type) > 1
6640 };
6641};
6642
6643template<typename IteratorType>
6644struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6645{
6646 using iterator_type = IteratorType;
6647 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6648 using base_adapter_type = iterator_input_adapter<iterator_type>;
6649 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6650
6651 static adapter_type create(IteratorType first, IteratorType last)
6652 {
6653 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6654 }
6655};
6656
6657// General purpose iterator-based input
6658template<typename IteratorType>
6659typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6660{
6661 using factory_type = iterator_input_adapter_factory<IteratorType>;
6662 return factory_type::create(first, last);
6663}
6664
6665// Convenience shorthand from container to iterator
6666// Enables ADL on begin(container) and end(container)
6667// Encloses the using declarations in namespace for not to leak them to outside scope
6668
6669namespace container_input_adapter_factory_impl
6670{
6671
6672using std::begin;
6673using std::end;
6674
6675template<typename ContainerType, typename Enable = void>
6677
6678template<typename ContainerType>
6680 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6681 {
6682 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6683
6684 static adapter_type create(const ContainerType& container)
6685{
6686 return input_adapter(begin(container), end(container));
6687}
6688 };
6689
6690} // namespace container_input_adapter_factory_impl
6691
6692template<typename ContainerType>
6693typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6694{
6695 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6696}
6697
6698#ifndef JSON_NO_IO
6699// Special cases with fast paths
6700inline file_input_adapter input_adapter(std::FILE* file)
6701{
6702 if (file == nullptr)
6703 {
6704 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6705 }
6706 return file_input_adapter(file);
6707}
6708
6709inline input_stream_adapter input_adapter(std::istream& stream)
6710{
6711 return input_stream_adapter(stream);
6712}
6713
6714inline input_stream_adapter input_adapter(std::istream&& stream)
6715{
6716 return input_stream_adapter(stream);
6717}
6718#endif // JSON_NO_IO
6719
6720using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6721
6722// Null-delimited strings, and the like.
6723template < typename CharT,
6724 typename std::enable_if <
6725 std::is_pointer<CharT>::value&&
6726 !std::is_array<CharT>::value&&
6727 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6728 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6729 int >::type = 0 >
6730contiguous_bytes_input_adapter input_adapter(CharT b)
6731{
6732 if (b == nullptr)
6733 {
6734 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6735 }
6736 auto length = std::strlen(reinterpret_cast<const char*>(b));
6737 const auto* ptr = reinterpret_cast<const char*>(b);
6738 return input_adapter(ptr, ptr + length);
6739}
6740
6741template<typename T, std::size_t N>
6742auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6743{
6744 return input_adapter(array, array + N);
6745}
6746
6747// This class only handles inputs of input_buffer_adapter type.
6748// It's required so that expressions like {ptr, len} can be implicitly cast
6749// to the correct adapter.
6750class span_input_adapter
6751{
6752 public:
6753 template < typename CharT,
6754 typename std::enable_if <
6755 std::is_pointer<CharT>::value&&
6756 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6757 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6758 int >::type = 0 >
6759 span_input_adapter(CharT b, std::size_t l)
6760 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6761
6762 template<class IteratorType,
6763 typename std::enable_if<
6764 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6765 int>::type = 0>
6766 span_input_adapter(IteratorType first, IteratorType last)
6767 : ia(input_adapter(first, last)) {}
6768
6769 contiguous_bytes_input_adapter&& get()
6770 {
6771 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6772 }
6773
6774 private:
6775 contiguous_bytes_input_adapter ia;
6776};
6777
6778} // namespace detail
6780
6781// #include <nlohmann/detail/input/json_sax.hpp>
6782// __ _____ _____ _____
6783// __| | __| | | | JSON for Modern C++
6784// | | |__ | | | | | | version 3.11.3
6785// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6786//
6787// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6788// SPDX-License-Identifier: MIT
6789
6790
6791
6792#include <cstddef>
6793#include <string> // string
6794#include <utility> // move
6795#include <vector> // vector
6796
6797// #include <nlohmann/detail/exceptions.hpp>
6798
6799// #include <nlohmann/detail/macro_scope.hpp>
6800
6801// #include <nlohmann/detail/string_concat.hpp>
6802
6803
6805
6814template<typename BasicJsonType>
6816{
6817 using number_integer_t = typename BasicJsonType::number_integer_t;
6818 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6819 using number_float_t = typename BasicJsonType::number_float_t;
6820 using string_t = typename BasicJsonType::string_t;
6821 using binary_t = typename BasicJsonType::binary_t;
6822
6827 virtual bool null() = 0;
6828
6834 virtual bool boolean(bool val) = 0;
6835
6841 virtual bool number_integer(number_integer_t val) = 0;
6842
6848 virtual bool number_unsigned(number_unsigned_t val) = 0;
6849
6856 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6857
6864 virtual bool string(string_t& val) = 0;
6865
6872 virtual bool binary(binary_t& val) = 0;
6873
6880 virtual bool start_object(std::size_t elements) = 0;
6881
6888 virtual bool key(string_t& val) = 0;
6889
6894 virtual bool end_object() = 0;
6895
6902 virtual bool start_array(std::size_t elements) = 0;
6903
6908 virtual bool end_array() = 0;
6909
6917 virtual bool parse_error(std::size_t position,
6918 const std::string& last_token,
6919 const detail::exception& ex) = 0;
6920
6921 json_sax() = default;
6922 json_sax(const json_sax&) = default;
6923 json_sax(json_sax&&) noexcept = default;
6924 json_sax& operator=(const json_sax&) = default;
6925 json_sax& operator=(json_sax&&) noexcept = default;
6926 virtual ~json_sax() = default;
6927};
6928
6929namespace detail
6930{
6944template<typename BasicJsonType>
6946{
6947 public:
6948 using number_integer_t = typename BasicJsonType::number_integer_t;
6949 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6950 using number_float_t = typename BasicJsonType::number_float_t;
6951 using string_t = typename BasicJsonType::string_t;
6952 using binary_t = typename BasicJsonType::binary_t;
6953
6959 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6960 : root(r), allow_exceptions(allow_exceptions_)
6961 {}
6962
6963 // make class move-only
6965 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6967 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6969
6970 bool null()
6971 {
6972 handle_value(nullptr);
6973 return true;
6974 }
6975
6976 bool boolean(bool val)
6977 {
6978 handle_value(val);
6979 return true;
6980 }
6981
6983 {
6984 handle_value(val);
6985 return true;
6986 }
6987
6989 {
6990 handle_value(val);
6991 return true;
6992 }
6993
6994 bool number_float(number_float_t val, const string_t& /*unused*/)
6995 {
6996 handle_value(val);
6997 return true;
6998 }
6999
7000 bool string(string_t& val)
7001 {
7002 handle_value(val);
7003 return true;
7004 }
7005
7006 bool binary(binary_t& val)
7007 {
7008 handle_value(std::move(val));
7009 return true;
7010 }
7011
7012 bool start_object(std::size_t len)
7013 {
7014 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
7015
7016 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7017 {
7018 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7019 }
7020
7021 return true;
7022 }
7023
7024 bool key(string_t& val)
7025 {
7026 JSON_ASSERT(!ref_stack.empty());
7027 JSON_ASSERT(ref_stack.back()->is_object());
7028
7029 // add null at given key and store the reference for later
7030 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
7031 return true;
7032 }
7033
7035 {
7036 JSON_ASSERT(!ref_stack.empty());
7037 JSON_ASSERT(ref_stack.back()->is_object());
7038
7039 ref_stack.back()->set_parents();
7040 ref_stack.pop_back();
7041 return true;
7042 }
7043
7044 bool start_array(std::size_t len)
7045 {
7046 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
7047
7048 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7049 {
7050 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7051 }
7052
7053 return true;
7054 }
7055
7057 {
7058 JSON_ASSERT(!ref_stack.empty());
7059 JSON_ASSERT(ref_stack.back()->is_array());
7060
7061 ref_stack.back()->set_parents();
7062 ref_stack.pop_back();
7063 return true;
7064 }
7065
7066 template<class Exception>
7067 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7068 const Exception& ex)
7069 {
7070 errored = true;
7071 static_cast<void>(ex);
7072 if (allow_exceptions)
7073 {
7074 JSON_THROW(ex);
7075 }
7076 return false;
7077 }
7078
7079 constexpr bool is_errored() const
7080 {
7081 return errored;
7082 }
7083
7084 private:
7091 template<typename Value>
7093 BasicJsonType* handle_value(Value&& v)
7094 {
7095 if (ref_stack.empty())
7096 {
7097 root = BasicJsonType(std::forward<Value>(v));
7098 return &root;
7099 }
7100
7101 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7102
7103 if (ref_stack.back()->is_array())
7104 {
7105 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
7106 return &(ref_stack.back()->m_data.m_value.array->back());
7107 }
7108
7109 JSON_ASSERT(ref_stack.back()->is_object());
7110 JSON_ASSERT(object_element);
7111 *object_element = BasicJsonType(std::forward<Value>(v));
7112 return object_element;
7113 }
7114
7116 BasicJsonType& root;
7118 std::vector<BasicJsonType*> ref_stack {};
7120 BasicJsonType* object_element = nullptr;
7122 bool errored = false;
7124 const bool allow_exceptions = true;
7125};
7126
7127template<typename BasicJsonType>
7129{
7130 public:
7131 using number_integer_t = typename BasicJsonType::number_integer_t;
7132 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7133 using number_float_t = typename BasicJsonType::number_float_t;
7134 using string_t = typename BasicJsonType::string_t;
7135 using binary_t = typename BasicJsonType::binary_t;
7136 using parser_callback_t = typename BasicJsonType::parser_callback_t;
7137 using parse_event_t = typename BasicJsonType::parse_event_t;
7138
7141 const bool allow_exceptions_ = true)
7142 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_)
7143 {
7144 keep_stack.push_back(true);
7145 }
7146
7147 // make class move-only
7149 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7151 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7153
7154 bool null()
7155 {
7156 handle_value(nullptr);
7157 return true;
7158 }
7159
7160 bool boolean(bool val)
7161 {
7162 handle_value(val);
7163 return true;
7164 }
7165
7167 {
7168 handle_value(val);
7169 return true;
7170 }
7171
7173 {
7174 handle_value(val);
7175 return true;
7176 }
7177
7178 bool number_float(number_float_t val, const string_t& /*unused*/)
7179 {
7180 handle_value(val);
7181 return true;
7182 }
7183
7184 bool string(string_t& val)
7185 {
7186 handle_value(val);
7187 return true;
7188 }
7189
7190 bool binary(binary_t& val)
7191 {
7192 handle_value(std::move(val));
7193 return true;
7194 }
7195
7196 bool start_object(std::size_t len)
7197 {
7198 // check callback for object start
7199 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7200 keep_stack.push_back(keep);
7201
7202 auto val = handle_value(BasicJsonType::value_t::object, true);
7203 ref_stack.push_back(val.second);
7204
7205 // check object limit
7206 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7207 {
7208 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7209 }
7210
7211 return true;
7212 }
7213
7214 bool key(string_t& val)
7215 {
7216 BasicJsonType k = BasicJsonType(val);
7217
7218 // check callback for key
7219 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7220 key_keep_stack.push_back(keep);
7221
7222 // add discarded value at given key and store the reference for later
7223 if (keep && ref_stack.back())
7224 {
7225 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7226 }
7227
7228 return true;
7229 }
7230
7232 {
7233 if (ref_stack.back())
7234 {
7235 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7236 {
7237 // discard object
7238 *ref_stack.back() = discarded;
7239 }
7240 else
7241 {
7242 ref_stack.back()->set_parents();
7243 }
7244 }
7245
7246 JSON_ASSERT(!ref_stack.empty());
7247 JSON_ASSERT(!keep_stack.empty());
7248 ref_stack.pop_back();
7249 keep_stack.pop_back();
7250
7251 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7252 {
7253 // remove discarded value
7254 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7255 {
7256 if (it->is_discarded())
7257 {
7258 ref_stack.back()->erase(it);
7259 break;
7260 }
7261 }
7262 }
7263
7264 return true;
7265 }
7266
7267 bool start_array(std::size_t len)
7268 {
7269 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7270 keep_stack.push_back(keep);
7271
7272 auto val = handle_value(BasicJsonType::value_t::array, true);
7273 ref_stack.push_back(val.second);
7274
7275 // check array limit
7276 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7277 {
7278 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7279 }
7280
7281 return true;
7282 }
7283
7285 {
7286 bool keep = true;
7287
7288 if (ref_stack.back())
7289 {
7290 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7291 if (keep)
7292 {
7293 ref_stack.back()->set_parents();
7294 }
7295 else
7296 {
7297 // discard array
7298 *ref_stack.back() = discarded;
7299 }
7300 }
7301
7302 JSON_ASSERT(!ref_stack.empty());
7303 JSON_ASSERT(!keep_stack.empty());
7304 ref_stack.pop_back();
7305 keep_stack.pop_back();
7306
7307 // remove discarded value
7308 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7309 {
7310 ref_stack.back()->m_data.m_value.array->pop_back();
7311 }
7312
7313 return true;
7314 }
7315
7316 template<class Exception>
7317 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7318 const Exception& ex)
7319 {
7320 errored = true;
7321 static_cast<void>(ex);
7322 if (allow_exceptions)
7323 {
7324 JSON_THROW(ex);
7325 }
7326 return false;
7327 }
7328
7329 constexpr bool is_errored() const
7330 {
7331 return errored;
7332 }
7333
7334 private:
7350 template<typename Value>
7351 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7352 {
7353 JSON_ASSERT(!keep_stack.empty());
7354
7355 // do not handle this value if we know it would be added to a discarded
7356 // container
7357 if (!keep_stack.back())
7358 {
7359 return {false, nullptr};
7360 }
7361
7362 // create value
7363 auto value = BasicJsonType(std::forward<Value>(v));
7364
7365 // check callback
7366 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7367
7368 // do not handle this value if we just learnt it shall be discarded
7369 if (!keep)
7370 {
7371 return {false, nullptr};
7372 }
7373
7374 if (ref_stack.empty())
7375 {
7376 root = std::move(value);
7377 return {true, & root};
7378 }
7379
7380 // skip this value if we already decided to skip the parent
7381 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7382 if (!ref_stack.back())
7383 {
7384 return {false, nullptr};
7385 }
7386
7387 // we now only expect arrays and objects
7388 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7389
7390 // array
7391 if (ref_stack.back()->is_array())
7392 {
7393 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7394 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
7395 }
7396
7397 // object
7398 JSON_ASSERT(ref_stack.back()->is_object());
7399 // check if we should store an element for the current key
7400 JSON_ASSERT(!key_keep_stack.empty());
7401 const bool store_element = key_keep_stack.back();
7402 key_keep_stack.pop_back();
7403
7404 if (!store_element)
7405 {
7406 return {false, nullptr};
7407 }
7408
7409 JSON_ASSERT(object_element);
7410 *object_element = std::move(value);
7411 return {true, object_element};
7412 }
7413
7415 BasicJsonType& root;
7417 std::vector<BasicJsonType*> ref_stack {};
7419 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
7421 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
7423 BasicJsonType* object_element = nullptr;
7425 bool errored = false;
7427 const parser_callback_t callback = nullptr;
7429 const bool allow_exceptions = true;
7431 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7432};
7433
7434template<typename BasicJsonType>
7436{
7437 public:
7438 using number_integer_t = typename BasicJsonType::number_integer_t;
7439 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7440 using number_float_t = typename BasicJsonType::number_float_t;
7441 using string_t = typename BasicJsonType::string_t;
7442 using binary_t = typename BasicJsonType::binary_t;
7443
7444 bool null()
7445 {
7446 return true;
7447 }
7448
7449 bool boolean(bool /*unused*/)
7450 {
7451 return true;
7452 }
7453
7455 {
7456 return true;
7457 }
7458
7460 {
7461 return true;
7462 }
7463
7464 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7465 {
7466 return true;
7467 }
7468
7469 bool string(string_t& /*unused*/)
7470 {
7471 return true;
7472 }
7473
7474 bool binary(binary_t& /*unused*/)
7475 {
7476 return true;
7477 }
7478
7479 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7480 {
7481 return true;
7482 }
7483
7484 bool key(string_t& /*unused*/)
7485 {
7486 return true;
7487 }
7488
7490 {
7491 return true;
7492 }
7493
7494 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7495 {
7496 return true;
7497 }
7498
7500 {
7501 return true;
7502 }
7503
7504 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7505 {
7506 return false;
7507 }
7508};
7509
7510} // namespace detail
7512
7513// #include <nlohmann/detail/input/lexer.hpp>
7514// __ _____ _____ _____
7515// __| | __| | | | JSON for Modern C++
7516// | | |__ | | | | | | version 3.11.3
7517// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7518//
7519// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
7520// SPDX-License-Identifier: MIT
7521
7522
7523
7524#include <array> // array
7525#include <clocale> // localeconv
7526#include <cstddef> // size_t
7527#include <cstdio> // snprintf
7528#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7529#include <initializer_list> // initializer_list
7530#include <string> // char_traits, string
7531#include <utility> // move
7532#include <vector> // vector
7533
7534// #include <nlohmann/detail/input/input_adapters.hpp>
7535
7536// #include <nlohmann/detail/input/position_t.hpp>
7537
7538// #include <nlohmann/detail/macro_scope.hpp>
7539
7540// #include <nlohmann/detail/meta/type_traits.hpp>
7541
7542
7544namespace detail
7545{
7546
7548// lexer //
7550
7551template<typename BasicJsonType>
7553{
7554 public:
7556 enum class token_type
7557 {
7558 uninitialized,
7559 literal_true,
7560 literal_false,
7561 literal_null,
7562 value_string,
7563 value_unsigned,
7564 value_integer,
7565 value_float,
7566 begin_array,
7567 begin_object,
7568 end_array,
7569 end_object,
7570 name_separator,
7571 value_separator,
7572 parse_error,
7573 end_of_input,
7574 literal_or_value
7575 };
7576
7580 static const char* token_type_name(const token_type t) noexcept
7581 {
7582 switch (t)
7583 {
7584 case token_type::uninitialized:
7585 return "<uninitialized>";
7586 case token_type::literal_true:
7587 return "true literal";
7588 case token_type::literal_false:
7589 return "false literal";
7590 case token_type::literal_null:
7591 return "null literal";
7592 case token_type::value_string:
7593 return "string literal";
7594 case token_type::value_unsigned:
7595 case token_type::value_integer:
7596 case token_type::value_float:
7597 return "number literal";
7598 case token_type::begin_array:
7599 return "'['";
7600 case token_type::begin_object:
7601 return "'{'";
7602 case token_type::end_array:
7603 return "']'";
7604 case token_type::end_object:
7605 return "'}'";
7606 case token_type::name_separator:
7607 return "':'";
7608 case token_type::value_separator:
7609 return "','";
7610 case token_type::parse_error:
7611 return "<parse error>";
7612 case token_type::end_of_input:
7613 return "end of input";
7614 case token_type::literal_or_value:
7615 return "'[', '{', or a literal";
7616 // LCOV_EXCL_START
7617 default: // catch non-enum values
7618 return "unknown token";
7619 // LCOV_EXCL_STOP
7620 }
7621 }
7622};
7628template<typename BasicJsonType, typename InputAdapterType>
7629class lexer : public lexer_base<BasicJsonType>
7630{
7631 using number_integer_t = typename BasicJsonType::number_integer_t;
7632 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7633 using number_float_t = typename BasicJsonType::number_float_t;
7634 using string_t = typename BasicJsonType::string_t;
7635 using char_type = typename InputAdapterType::char_type;
7636 using char_int_type = typename char_traits<char_type>::int_type;
7637
7638 public:
7640
7641 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7642 : ia(std::move(adapter))
7643 , ignore_comments(ignore_comments_)
7644 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7645 {}
7646
7647 // delete because of pointer members
7648 lexer(const lexer&) = delete;
7649 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7650 lexer& operator=(lexer&) = delete;
7651 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7652 ~lexer() = default;
7653
7654 private:
7656 // locales
7658
7661 static char get_decimal_point() noexcept
7662 {
7663 const auto* loc = localeconv();
7664 JSON_ASSERT(loc != nullptr);
7665 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7666 }
7667
7669 // scan functions
7671
7687 int get_codepoint()
7688 {
7689 // this function only makes sense after reading `\u`
7690 JSON_ASSERT(current == 'u');
7691 int codepoint = 0;
7692
7693 const auto factors = { 12u, 8u, 4u, 0u };
7694 for (const auto factor : factors)
7695 {
7696 get();
7697
7698 if (current >= '0' && current <= '9')
7699 {
7700 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7701 }
7702 else if (current >= 'A' && current <= 'F')
7703 {
7704 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7705 }
7706 else if (current >= 'a' && current <= 'f')
7707 {
7708 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7709 }
7710 else
7711 {
7712 return -1;
7713 }
7714 }
7715
7716 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7717 return codepoint;
7718 }
7719
7735 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7736 {
7737 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7738 add(current);
7739
7740 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7741 {
7742 get();
7743 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7744 {
7745 add(current);
7746 }
7747 else
7748 {
7749 error_message = "invalid string: ill-formed UTF-8 byte";
7750 return false;
7751 }
7752 }
7753
7754 return true;
7755 }
7756
7772 token_type scan_string()
7773 {
7774 // reset token_buffer (ignore opening quote)
7775 reset();
7776
7777 // we entered the function by reading an open quote
7778 JSON_ASSERT(current == '\"');
7779
7780 while (true)
7781 {
7782 // get next character
7783 switch (get())
7784 {
7785 // end of file while parsing string
7786 case char_traits<char_type>::eof():
7787 {
7788 error_message = "invalid string: missing closing quote";
7789 return token_type::parse_error;
7790 }
7791
7792 // closing quote
7793 case '\"':
7794 {
7795 return token_type::value_string;
7796 }
7797
7798 // escapes
7799 case '\\':
7800 {
7801 switch (get())
7802 {
7803 // quotation mark
7804 case '\"':
7805 add('\"');
7806 break;
7807 // reverse solidus
7808 case '\\':
7809 add('\\');
7810 break;
7811 // solidus
7812 case '/':
7813 add('/');
7814 break;
7815 // backspace
7816 case 'b':
7817 add('\b');
7818 break;
7819 // form feed
7820 case 'f':
7821 add('\f');
7822 break;
7823 // line feed
7824 case 'n':
7825 add('\n');
7826 break;
7827 // carriage return
7828 case 'r':
7829 add('\r');
7830 break;
7831 // tab
7832 case 't':
7833 add('\t');
7834 break;
7835
7836 // unicode escapes
7837 case 'u':
7838 {
7839 const int codepoint1 = get_codepoint();
7840 int codepoint = codepoint1; // start with codepoint1
7841
7842 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7843 {
7844 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7845 return token_type::parse_error;
7846 }
7847
7848 // check if code point is a high surrogate
7849 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7850 {
7851 // expect next \uxxxx entry
7852 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7853 {
7854 const int codepoint2 = get_codepoint();
7855
7856 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7857 {
7858 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7859 return token_type::parse_error;
7860 }
7861
7862 // check if codepoint2 is a low surrogate
7863 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7864 {
7865 // overwrite codepoint
7866 codepoint = static_cast<int>(
7867 // high surrogate occupies the most significant 22 bits
7868 (static_cast<unsigned int>(codepoint1) << 10u)
7869 // low surrogate occupies the least significant 15 bits
7870 + static_cast<unsigned int>(codepoint2)
7871 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7872 // in the result, so we have to subtract with:
7873 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7874 - 0x35FDC00u);
7875 }
7876 else
7877 {
7878 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7879 return token_type::parse_error;
7880 }
7881 }
7882 else
7883 {
7884 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7885 return token_type::parse_error;
7886 }
7887 }
7888 else
7889 {
7890 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7891 {
7892 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7893 return token_type::parse_error;
7894 }
7895 }
7896
7897 // result of the above calculation yields a proper codepoint
7898 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7899
7900 // translate codepoint into bytes
7901 if (codepoint < 0x80)
7902 {
7903 // 1-byte characters: 0xxxxxxx (ASCII)
7904 add(static_cast<char_int_type>(codepoint));
7905 }
7906 else if (codepoint <= 0x7FF)
7907 {
7908 // 2-byte characters: 110xxxxx 10xxxxxx
7909 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7910 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7911 }
7912 else if (codepoint <= 0xFFFF)
7913 {
7914 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7915 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7916 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7917 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7918 }
7919 else
7920 {
7921 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7922 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7923 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7924 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7925 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7926 }
7927
7928 break;
7929 }
7930
7931 // other characters after escape
7932 default:
7933 error_message = "invalid string: forbidden character after backslash";
7934 return token_type::parse_error;
7935 }
7936
7937 break;
7938 }
7939
7940 // invalid control characters
7941 case 0x00:
7942 {
7943 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7944 return token_type::parse_error;
7945 }
7946
7947 case 0x01:
7948 {
7949 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7950 return token_type::parse_error;
7951 }
7952
7953 case 0x02:
7954 {
7955 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7956 return token_type::parse_error;
7957 }
7958
7959 case 0x03:
7960 {
7961 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7962 return token_type::parse_error;
7963 }
7964
7965 case 0x04:
7966 {
7967 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7968 return token_type::parse_error;
7969 }
7970
7971 case 0x05:
7972 {
7973 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7974 return token_type::parse_error;
7975 }
7976
7977 case 0x06:
7978 {
7979 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7980 return token_type::parse_error;
7981 }
7982
7983 case 0x07:
7984 {
7985 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7986 return token_type::parse_error;
7987 }
7988
7989 case 0x08:
7990 {
7991 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7992 return token_type::parse_error;
7993 }
7994
7995 case 0x09:
7996 {
7997 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7998 return token_type::parse_error;
7999 }
8000
8001 case 0x0A:
8002 {
8003 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
8004 return token_type::parse_error;
8005 }
8006
8007 case 0x0B:
8008 {
8009 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
8010 return token_type::parse_error;
8011 }
8012
8013 case 0x0C:
8014 {
8015 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
8016 return token_type::parse_error;
8017 }
8018
8019 case 0x0D:
8020 {
8021 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
8022 return token_type::parse_error;
8023 }
8024
8025 case 0x0E:
8026 {
8027 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
8028 return token_type::parse_error;
8029 }
8030
8031 case 0x0F:
8032 {
8033 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
8034 return token_type::parse_error;
8035 }
8036
8037 case 0x10:
8038 {
8039 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
8040 return token_type::parse_error;
8041 }
8042
8043 case 0x11:
8044 {
8045 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
8046 return token_type::parse_error;
8047 }
8048
8049 case 0x12:
8050 {
8051 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
8052 return token_type::parse_error;
8053 }
8054
8055 case 0x13:
8056 {
8057 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
8058 return token_type::parse_error;
8059 }
8060
8061 case 0x14:
8062 {
8063 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
8064 return token_type::parse_error;
8065 }
8066
8067 case 0x15:
8068 {
8069 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
8070 return token_type::parse_error;
8071 }
8072
8073 case 0x16:
8074 {
8075 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
8076 return token_type::parse_error;
8077 }
8078
8079 case 0x17:
8080 {
8081 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
8082 return token_type::parse_error;
8083 }
8084
8085 case 0x18:
8086 {
8087 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
8088 return token_type::parse_error;
8089 }
8090
8091 case 0x19:
8092 {
8093 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
8094 return token_type::parse_error;
8095 }
8096
8097 case 0x1A:
8098 {
8099 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
8100 return token_type::parse_error;
8101 }
8102
8103 case 0x1B:
8104 {
8105 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
8106 return token_type::parse_error;
8107 }
8108
8109 case 0x1C:
8110 {
8111 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
8112 return token_type::parse_error;
8113 }
8114
8115 case 0x1D:
8116 {
8117 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
8118 return token_type::parse_error;
8119 }
8120
8121 case 0x1E:
8122 {
8123 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
8124 return token_type::parse_error;
8125 }
8126
8127 case 0x1F:
8128 {
8129 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
8130 return token_type::parse_error;
8131 }
8132
8133 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
8134 case 0x20:
8135 case 0x21:
8136 case 0x23:
8137 case 0x24:
8138 case 0x25:
8139 case 0x26:
8140 case 0x27:
8141 case 0x28:
8142 case 0x29:
8143 case 0x2A:
8144 case 0x2B:
8145 case 0x2C:
8146 case 0x2D:
8147 case 0x2E:
8148 case 0x2F:
8149 case 0x30:
8150 case 0x31:
8151 case 0x32:
8152 case 0x33:
8153 case 0x34:
8154 case 0x35:
8155 case 0x36:
8156 case 0x37:
8157 case 0x38:
8158 case 0x39:
8159 case 0x3A:
8160 case 0x3B:
8161 case 0x3C:
8162 case 0x3D:
8163 case 0x3E:
8164 case 0x3F:
8165 case 0x40:
8166 case 0x41:
8167 case 0x42:
8168 case 0x43:
8169 case 0x44:
8170 case 0x45:
8171 case 0x46:
8172 case 0x47:
8173 case 0x48:
8174 case 0x49:
8175 case 0x4A:
8176 case 0x4B:
8177 case 0x4C:
8178 case 0x4D:
8179 case 0x4E:
8180 case 0x4F:
8181 case 0x50:
8182 case 0x51:
8183 case 0x52:
8184 case 0x53:
8185 case 0x54:
8186 case 0x55:
8187 case 0x56:
8188 case 0x57:
8189 case 0x58:
8190 case 0x59:
8191 case 0x5A:
8192 case 0x5B:
8193 case 0x5D:
8194 case 0x5E:
8195 case 0x5F:
8196 case 0x60:
8197 case 0x61:
8198 case 0x62:
8199 case 0x63:
8200 case 0x64:
8201 case 0x65:
8202 case 0x66:
8203 case 0x67:
8204 case 0x68:
8205 case 0x69:
8206 case 0x6A:
8207 case 0x6B:
8208 case 0x6C:
8209 case 0x6D:
8210 case 0x6E:
8211 case 0x6F:
8212 case 0x70:
8213 case 0x71:
8214 case 0x72:
8215 case 0x73:
8216 case 0x74:
8217 case 0x75:
8218 case 0x76:
8219 case 0x77:
8220 case 0x78:
8221 case 0x79:
8222 case 0x7A:
8223 case 0x7B:
8224 case 0x7C:
8225 case 0x7D:
8226 case 0x7E:
8227 case 0x7F:
8228 {
8229 add(current);
8230 break;
8231 }
8232
8233 // U+0080..U+07FF: bytes C2..DF 80..BF
8234 case 0xC2:
8235 case 0xC3:
8236 case 0xC4:
8237 case 0xC5:
8238 case 0xC6:
8239 case 0xC7:
8240 case 0xC8:
8241 case 0xC9:
8242 case 0xCA:
8243 case 0xCB:
8244 case 0xCC:
8245 case 0xCD:
8246 case 0xCE:
8247 case 0xCF:
8248 case 0xD0:
8249 case 0xD1:
8250 case 0xD2:
8251 case 0xD3:
8252 case 0xD4:
8253 case 0xD5:
8254 case 0xD6:
8255 case 0xD7:
8256 case 0xD8:
8257 case 0xD9:
8258 case 0xDA:
8259 case 0xDB:
8260 case 0xDC:
8261 case 0xDD:
8262 case 0xDE:
8263 case 0xDF:
8264 {
8265 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8266 {
8267 return token_type::parse_error;
8268 }
8269 break;
8270 }
8271
8272 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8273 case 0xE0:
8274 {
8275 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8276 {
8277 return token_type::parse_error;
8278 }
8279 break;
8280 }
8281
8282 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8283 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8284 case 0xE1:
8285 case 0xE2:
8286 case 0xE3:
8287 case 0xE4:
8288 case 0xE5:
8289 case 0xE6:
8290 case 0xE7:
8291 case 0xE8:
8292 case 0xE9:
8293 case 0xEA:
8294 case 0xEB:
8295 case 0xEC:
8296 case 0xEE:
8297 case 0xEF:
8298 {
8299 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8300 {
8301 return token_type::parse_error;
8302 }
8303 break;
8304 }
8305
8306 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8307 case 0xED:
8308 {
8309 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8310 {
8311 return token_type::parse_error;
8312 }
8313 break;
8314 }
8315
8316 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8317 case 0xF0:
8318 {
8319 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8320 {
8321 return token_type::parse_error;
8322 }
8323 break;
8324 }
8325
8326 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8327 case 0xF1:
8328 case 0xF2:
8329 case 0xF3:
8330 {
8331 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8332 {
8333 return token_type::parse_error;
8334 }
8335 break;
8336 }
8337
8338 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8339 case 0xF4:
8340 {
8341 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8342 {
8343 return token_type::parse_error;
8344 }
8345 break;
8346 }
8347
8348 // remaining bytes (80..C1 and F5..FF) are ill-formed
8349 default:
8350 {
8351 error_message = "invalid string: ill-formed UTF-8 byte";
8352 return token_type::parse_error;
8353 }
8354 }
8355 }
8356 }
8357
8362 bool scan_comment()
8363 {
8364 switch (get())
8365 {
8366 // single-line comments skip input until a newline or EOF is read
8367 case '/':
8368 {
8369 while (true)
8370 {
8371 switch (get())
8372 {
8373 case '\n':
8374 case '\r':
8375 case char_traits<char_type>::eof():
8376 case '\0':
8377 return true;
8378
8379 default:
8380 break;
8381 }
8382 }
8383 }
8384
8385 // multi-line comments skip input until */ is read
8386 case '*':
8387 {
8388 while (true)
8389 {
8390 switch (get())
8391 {
8392 case char_traits<char_type>::eof():
8393 case '\0':
8394 {
8395 error_message = "invalid comment; missing closing '*/'";
8396 return false;
8397 }
8398
8399 case '*':
8400 {
8401 switch (get())
8402 {
8403 case '/':
8404 return true;
8405
8406 default:
8407 {
8408 unget();
8409 continue;
8410 }
8411 }
8412 }
8413
8414 default:
8415 continue;
8416 }
8417 }
8418 }
8419
8420 // unexpected character after reading '/'
8421 default:
8422 {
8423 error_message = "invalid comment; expecting '/' or '*' after '/'";
8424 return false;
8425 }
8426 }
8427 }
8428
8430 static void strtof(float& f, const char* str, char** endptr) noexcept
8431 {
8432 f = std::strtof(str, endptr);
8433 }
8434
8436 static void strtof(double& f, const char* str, char** endptr) noexcept
8437 {
8438 f = std::strtod(str, endptr);
8439 }
8440
8442 static void strtof(long double& f, const char* str, char** endptr) noexcept
8443 {
8444 f = std::strtold(str, endptr);
8445 }
8446
8487 token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
8488 {
8489 // reset token_buffer to store the number's bytes
8490 reset();
8491
8492 // the type of the parsed number; initially set to unsigned; will be
8493 // changed if minus sign, decimal point or exponent is read
8494 token_type number_type = token_type::value_unsigned;
8495
8496 // state (init): we just found out we need to scan a number
8497 switch (current)
8498 {
8499 case '-':
8500 {
8501 add(current);
8502 goto scan_number_minus;
8503 }
8504
8505 case '0':
8506 {
8507 add(current);
8508 goto scan_number_zero;
8509 }
8510
8511 case '1':
8512 case '2':
8513 case '3':
8514 case '4':
8515 case '5':
8516 case '6':
8517 case '7':
8518 case '8':
8519 case '9':
8520 {
8521 add(current);
8522 goto scan_number_any1;
8523 }
8524
8525 // all other characters are rejected outside scan_number()
8526 default: // LCOV_EXCL_LINE
8527 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8528 }
8529
8530scan_number_minus:
8531 // state: we just parsed a leading minus sign
8532 number_type = token_type::value_integer;
8533 switch (get())
8534 {
8535 case '0':
8536 {
8537 add(current);
8538 goto scan_number_zero;
8539 }
8540
8541 case '1':
8542 case '2':
8543 case '3':
8544 case '4':
8545 case '5':
8546 case '6':
8547 case '7':
8548 case '8':
8549 case '9':
8550 {
8551 add(current);
8552 goto scan_number_any1;
8553 }
8554
8555 default:
8556 {
8557 error_message = "invalid number; expected digit after '-'";
8558 return token_type::parse_error;
8559 }
8560 }
8561
8562scan_number_zero:
8563 // state: we just parse a zero (maybe with a leading minus sign)
8564 switch (get())
8565 {
8566 case '.':
8567 {
8568 add(decimal_point_char);
8569 decimal_point_position = token_buffer.size() - 1;
8570 goto scan_number_decimal1;
8571 }
8572
8573 case 'e':
8574 case 'E':
8575 {
8576 add(current);
8577 goto scan_number_exponent;
8578 }
8579
8580 default:
8581 goto scan_number_done;
8582 }
8583
8584scan_number_any1:
8585 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8586 switch (get())
8587 {
8588 case '0':
8589 case '1':
8590 case '2':
8591 case '3':
8592 case '4':
8593 case '5':
8594 case '6':
8595 case '7':
8596 case '8':
8597 case '9':
8598 {
8599 add(current);
8600 goto scan_number_any1;
8601 }
8602
8603 case '.':
8604 {
8605 add(decimal_point_char);
8606 decimal_point_position = token_buffer.size() - 1;
8607 goto scan_number_decimal1;
8608 }
8609
8610 case 'e':
8611 case 'E':
8612 {
8613 add(current);
8614 goto scan_number_exponent;
8615 }
8616
8617 default:
8618 goto scan_number_done;
8619 }
8620
8621scan_number_decimal1:
8622 // state: we just parsed a decimal point
8623 number_type = token_type::value_float;
8624 switch (get())
8625 {
8626 case '0':
8627 case '1':
8628 case '2':
8629 case '3':
8630 case '4':
8631 case '5':
8632 case '6':
8633 case '7':
8634 case '8':
8635 case '9':
8636 {
8637 add(current);
8638 goto scan_number_decimal2;
8639 }
8640
8641 default:
8642 {
8643 error_message = "invalid number; expected digit after '.'";
8644 return token_type::parse_error;
8645 }
8646 }
8647
8648scan_number_decimal2:
8649 // we just parsed at least one number after a decimal point
8650 switch (get())
8651 {
8652 case '0':
8653 case '1':
8654 case '2':
8655 case '3':
8656 case '4':
8657 case '5':
8658 case '6':
8659 case '7':
8660 case '8':
8661 case '9':
8662 {
8663 add(current);
8664 goto scan_number_decimal2;
8665 }
8666
8667 case 'e':
8668 case 'E':
8669 {
8670 add(current);
8671 goto scan_number_exponent;
8672 }
8673
8674 default:
8675 goto scan_number_done;
8676 }
8677
8678scan_number_exponent:
8679 // we just parsed an exponent
8680 number_type = token_type::value_float;
8681 switch (get())
8682 {
8683 case '+':
8684 case '-':
8685 {
8686 add(current);
8687 goto scan_number_sign;
8688 }
8689
8690 case '0':
8691 case '1':
8692 case '2':
8693 case '3':
8694 case '4':
8695 case '5':
8696 case '6':
8697 case '7':
8698 case '8':
8699 case '9':
8700 {
8701 add(current);
8702 goto scan_number_any2;
8703 }
8704
8705 default:
8706 {
8707 error_message =
8708 "invalid number; expected '+', '-', or digit after exponent";
8709 return token_type::parse_error;
8710 }
8711 }
8712
8713scan_number_sign:
8714 // we just parsed an exponent sign
8715 switch (get())
8716 {
8717 case '0':
8718 case '1':
8719 case '2':
8720 case '3':
8721 case '4':
8722 case '5':
8723 case '6':
8724 case '7':
8725 case '8':
8726 case '9':
8727 {
8728 add(current);
8729 goto scan_number_any2;
8730 }
8731
8732 default:
8733 {
8734 error_message = "invalid number; expected digit after exponent sign";
8735 return token_type::parse_error;
8736 }
8737 }
8738
8739scan_number_any2:
8740 // we just parsed a number after the exponent or exponent sign
8741 switch (get())
8742 {
8743 case '0':
8744 case '1':
8745 case '2':
8746 case '3':
8747 case '4':
8748 case '5':
8749 case '6':
8750 case '7':
8751 case '8':
8752 case '9':
8753 {
8754 add(current);
8755 goto scan_number_any2;
8756 }
8757
8758 default:
8759 goto scan_number_done;
8760 }
8761
8762scan_number_done:
8763 // unget the character after the number (we only read it to know that
8764 // we are done scanning a number)
8765 unget();
8766
8767 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8768 errno = 0;
8769
8770 // try to parse integers first and fall back to floats
8771 if (number_type == token_type::value_unsigned)
8772 {
8773 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8774
8775 // we checked the number format before
8776 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8777
8778 if (errno != ERANGE)
8779 {
8780 value_unsigned = static_cast<number_unsigned_t>(x);
8781 if (value_unsigned == x)
8782 {
8783 return token_type::value_unsigned;
8784 }
8785 }
8786 }
8787 else if (number_type == token_type::value_integer)
8788 {
8789 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8790
8791 // we checked the number format before
8792 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8793
8794 if (errno != ERANGE)
8795 {
8796 value_integer = static_cast<number_integer_t>(x);
8797 if (value_integer == x)
8798 {
8799 return token_type::value_integer;
8800 }
8801 }
8802 }
8803
8804 // this code is reached if we parse a floating-point number or if an
8805 // integer conversion above failed
8806 strtof(value_float, token_buffer.data(), &endptr);
8807
8808 // we checked the number format before
8809 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8810
8811 return token_type::value_float;
8812 }
8813
8820 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8821 token_type return_type)
8822 {
8823 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8824 for (std::size_t i = 1; i < length; ++i)
8825 {
8826 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8827 {
8828 error_message = "invalid literal";
8829 return token_type::parse_error;
8830 }
8831 }
8832 return return_type;
8833 }
8834
8836 // input management
8838
8840 void reset() noexcept
8841 {
8842 token_buffer.clear();
8843 token_string.clear();
8844 decimal_point_position = std::string::npos;
8845 token_string.push_back(char_traits<char_type>::to_char_type(current));
8846 }
8847
8848 /*
8849 @brief get next character from the input
8850
8851 This function provides the interface to the used input adapter. It does
8852 not throw in case the input reached EOF, but returns a
8853 `char_traits<char>::eof()` in that case. Stores the scanned characters
8854 for use in error messages.
8855
8856 @return character read from the input
8857 */
8858 char_int_type get()
8859 {
8860 ++position.chars_read_total;
8861 ++position.chars_read_current_line;
8862
8863 if (next_unget)
8864 {
8865 // just reset the next_unget variable and work with current
8866 next_unget = false;
8867 }
8868 else
8869 {
8870 current = ia.get_character();
8871 }
8872
8873 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8874 {
8875 token_string.push_back(char_traits<char_type>::to_char_type(current));
8876 }
8877
8878 if (current == '\n')
8879 {
8880 ++position.lines_read;
8881 position.chars_read_current_line = 0;
8882 }
8883
8884 return current;
8885 }
8886
8895 void unget()
8896 {
8897 next_unget = true;
8898
8899 --position.chars_read_total;
8900
8901 // in case we "unget" a newline, we have to also decrement the lines_read
8902 if (position.chars_read_current_line == 0)
8903 {
8904 if (position.lines_read > 0)
8905 {
8906 --position.lines_read;
8907 }
8908 }
8909 else
8910 {
8911 --position.chars_read_current_line;
8912 }
8913
8914 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8915 {
8916 JSON_ASSERT(!token_string.empty());
8917 token_string.pop_back();
8918 }
8919 }
8920
8922 void add(char_int_type c)
8923 {
8924 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8925 }
8926
8927 public:
8929 // value getters
8931
8933 constexpr number_integer_t get_number_integer() const noexcept
8934 {
8935 return value_integer;
8936 }
8937
8939 constexpr number_unsigned_t get_number_unsigned() const noexcept
8940 {
8941 return value_unsigned;
8942 }
8943
8945 constexpr number_float_t get_number_float() const noexcept
8946 {
8947 return value_float;
8948 }
8949
8951 string_t& get_string()
8952 {
8953 // translate decimal points from locale back to '.' (#4084)
8954 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8955 {
8956 token_buffer[decimal_point_position] = '.';
8957 }
8958 return token_buffer;
8959 }
8960
8962 // diagnostics
8964
8966 constexpr position_t get_position() const noexcept
8967 {
8968 return position;
8969 }
8970
8974 std::string get_token_string() const
8975 {
8976 // escape control characters
8977 std::string result;
8978 for (const auto c : token_string)
8979 {
8980 if (static_cast<unsigned char>(c) <= '\x1F')
8981 {
8982 // escape control characters
8983 std::array<char, 9> cs{{}};
8984 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8985 result += cs.data();
8986 }
8987 else
8988 {
8989 // add character as is
8990 result.push_back(static_cast<std::string::value_type>(c));
8991 }
8992 }
8993
8994 return result;
8995 }
8996
8999 constexpr const char* get_error_message() const noexcept
9000 {
9001 return error_message;
9002 }
9003
9005 // actual scanner
9007
9013 {
9014 if (get() == 0xEF)
9015 {
9016 // check if we completely parse the BOM
9017 return get() == 0xBB && get() == 0xBF;
9018 }
9019
9020 // the first character is not the beginning of the BOM; unget it to
9021 // process is later
9022 unget();
9023 return true;
9024 }
9025
9027 {
9028 do
9029 {
9030 get();
9031 }
9032 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
9033 }
9034
9036 {
9037 // initially, skip the BOM
9038 if (position.chars_read_total == 0 && !skip_bom())
9039 {
9040 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
9041 return token_type::parse_error;
9042 }
9043
9044 // read next character and ignore whitespace
9045 skip_whitespace();
9046
9047 // ignore comments
9048 while (ignore_comments && current == '/')
9049 {
9050 if (!scan_comment())
9051 {
9052 return token_type::parse_error;
9053 }
9054
9055 // skip following whitespace
9056 skip_whitespace();
9057 }
9058
9059 switch (current)
9060 {
9061 // structural characters
9062 case '[':
9063 return token_type::begin_array;
9064 case ']':
9065 return token_type::end_array;
9066 case '{':
9067 return token_type::begin_object;
9068 case '}':
9069 return token_type::end_object;
9070 case ':':
9071 return token_type::name_separator;
9072 case ',':
9073 return token_type::value_separator;
9074
9075 // literals
9076 case 't':
9077 {
9078 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
9079 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
9080 }
9081 case 'f':
9082 {
9083 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
9084 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
9085 }
9086 case 'n':
9087 {
9088 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
9089 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
9090 }
9091
9092 // string
9093 case '\"':
9094 return scan_string();
9095
9096 // number
9097 case '-':
9098 case '0':
9099 case '1':
9100 case '2':
9101 case '3':
9102 case '4':
9103 case '5':
9104 case '6':
9105 case '7':
9106 case '8':
9107 case '9':
9108 return scan_number();
9109
9110 // end of input (the null byte is needed when parsing from
9111 // string literals)
9112 case '\0':
9114 return token_type::end_of_input;
9115
9116 // error
9117 default:
9118 error_message = "invalid literal";
9119 return token_type::parse_error;
9120 }
9121 }
9122
9123 private:
9125 InputAdapterType ia;
9126
9128 const bool ignore_comments = false;
9129
9131 char_int_type current = char_traits<char_type>::eof();
9132
9134 bool next_unget = false;
9135
9137 position_t position {};
9138
9140 std::vector<char_type> token_string {};
9141
9143 string_t token_buffer {};
9144
9146 const char* error_message = "";
9147
9148 // number values
9149 number_integer_t value_integer = 0;
9150 number_unsigned_t value_unsigned = 0;
9151 number_float_t value_float = 0;
9152
9154 const char_int_type decimal_point_char = '.';
9156 std::size_t decimal_point_position = std::string::npos;
9157};
9158
9159} // namespace detail
9161
9162// #include <nlohmann/detail/macro_scope.hpp>
9163
9164// #include <nlohmann/detail/meta/is_sax.hpp>
9165// __ _____ _____ _____
9166// __| | __| | | | JSON for Modern C++
9167// | | |__ | | | | | | version 3.11.3
9168// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9169//
9170// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
9171// SPDX-License-Identifier: MIT
9172
9173
9174
9175#include <cstdint> // size_t
9176#include <utility> // declval
9177#include <string> // string
9178
9179// #include <nlohmann/detail/abi_macros.hpp>
9180
9181// #include <nlohmann/detail/meta/detected.hpp>
9182
9183// #include <nlohmann/detail/meta/type_traits.hpp>
9184
9185
9187namespace detail
9188{
9189
9190template<typename T>
9191using null_function_t = decltype(std::declval<T&>().null());
9192
9193template<typename T>
9194using boolean_function_t =
9195 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9196
9197template<typename T, typename Integer>
9198using number_integer_function_t =
9199 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9200
9201template<typename T, typename Unsigned>
9202using number_unsigned_function_t =
9203 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9204
9205template<typename T, typename Float, typename String>
9206using number_float_function_t = decltype(std::declval<T&>().number_float(
9207 std::declval<Float>(), std::declval<const String&>()));
9208
9209template<typename T, typename String>
9210using string_function_t =
9211 decltype(std::declval<T&>().string(std::declval<String&>()));
9212
9213template<typename T, typename Binary>
9214using binary_function_t =
9215 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9216
9217template<typename T>
9218using start_object_function_t =
9219 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9220
9221template<typename T, typename String>
9222using key_function_t =
9223 decltype(std::declval<T&>().key(std::declval<String&>()));
9224
9225template<typename T>
9226using end_object_function_t = decltype(std::declval<T&>().end_object());
9227
9228template<typename T>
9229using start_array_function_t =
9230 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9231
9232template<typename T>
9233using end_array_function_t = decltype(std::declval<T&>().end_array());
9234
9235template<typename T, typename Exception>
9236using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9237 std::declval<std::size_t>(), std::declval<const std::string&>(),
9238 std::declval<const Exception&>()));
9239
9240template<typename SAX, typename BasicJsonType>
9241struct is_sax
9242{
9243 private:
9244 static_assert(is_basic_json<BasicJsonType>::value,
9245 "BasicJsonType must be of type basic_json<...>");
9246
9247 using number_integer_t = typename BasicJsonType::number_integer_t;
9248 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9249 using number_float_t = typename BasicJsonType::number_float_t;
9250 using string_t = typename BasicJsonType::string_t;
9251 using binary_t = typename BasicJsonType::binary_t;
9252 using exception_t = typename BasicJsonType::exception;
9253
9254 public:
9255 static constexpr bool value =
9256 is_detected_exact<bool, null_function_t, SAX>::value &&
9257 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9258 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9259 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9260 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9261 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9262 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9263 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9264 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9265 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9266 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9267 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9268 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9269};
9270
9271template<typename SAX, typename BasicJsonType>
9272struct is_sax_static_asserts
9273{
9274 private:
9275 static_assert(is_basic_json<BasicJsonType>::value,
9276 "BasicJsonType must be of type basic_json<...>");
9277
9278 using number_integer_t = typename BasicJsonType::number_integer_t;
9279 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9280 using number_float_t = typename BasicJsonType::number_float_t;
9281 using string_t = typename BasicJsonType::string_t;
9282 using binary_t = typename BasicJsonType::binary_t;
9283 using exception_t = typename BasicJsonType::exception;
9284
9285 public:
9286 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9287 "Missing/invalid function: bool null()");
9288 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9289 "Missing/invalid function: bool boolean(bool)");
9290 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9291 "Missing/invalid function: bool boolean(bool)");
9292 static_assert(
9293 is_detected_exact<bool, number_integer_function_t, SAX,
9294 number_integer_t>::value,
9295 "Missing/invalid function: bool number_integer(number_integer_t)");
9296 static_assert(
9297 is_detected_exact<bool, number_unsigned_function_t, SAX,
9298 number_unsigned_t>::value,
9299 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9300 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9301 number_float_t, string_t>::value,
9302 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9303 static_assert(
9304 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9305 "Missing/invalid function: bool string(string_t&)");
9306 static_assert(
9307 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9308 "Missing/invalid function: bool binary(binary_t&)");
9309 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9310 "Missing/invalid function: bool start_object(std::size_t)");
9311 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9312 "Missing/invalid function: bool key(string_t&)");
9313 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9314 "Missing/invalid function: bool end_object()");
9315 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9316 "Missing/invalid function: bool start_array(std::size_t)");
9317 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9318 "Missing/invalid function: bool end_array()");
9319 static_assert(
9320 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9321 "Missing/invalid function: bool parse_error(std::size_t, const "
9322 "std::string&, const exception&)");
9323};
9324
9325} // namespace detail
9327
9328// #include <nlohmann/detail/meta/type_traits.hpp>
9329
9330// #include <nlohmann/detail/string_concat.hpp>
9331
9332// #include <nlohmann/detail/value_t.hpp>
9333
9334
9336namespace detail
9337{
9338
9341{
9342 error,
9343 ignore,
9344 store
9345};
9346
9354static inline bool little_endianness(int num = 1) noexcept
9355{
9356 return *reinterpret_cast<char*>(&num) == 1;
9357}
9358
9360// binary reader //
9362
9366template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9368{
9369 using number_integer_t = typename BasicJsonType::number_integer_t;
9370 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9371 using number_float_t = typename BasicJsonType::number_float_t;
9372 using string_t = typename BasicJsonType::string_t;
9373 using binary_t = typename BasicJsonType::binary_t;
9374 using json_sax_t = SAX;
9375 using char_type = typename InputAdapterType::char_type;
9376 using char_int_type = typename char_traits<char_type>::int_type;
9377
9378 public:
9384 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9385 {
9386 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
9387 }
9388
9389 // make class move-only
9391 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9393 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9394 ~binary_reader() = default;
9395
9405 bool sax_parse(const input_format_t format,
9406 json_sax_t* sax_,
9407 const bool strict = true,
9408 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9409 {
9410 sax = sax_;
9411 bool result = false;
9412
9413 switch (format)
9414 {
9415 case input_format_t::bson:
9416 result = parse_bson_internal();
9417 break;
9418
9419 case input_format_t::cbor:
9420 result = parse_cbor_internal(true, tag_handler);
9421 break;
9422
9423 case input_format_t::msgpack:
9424 result = parse_msgpack_internal();
9425 break;
9426
9427 case input_format_t::ubjson:
9428 case input_format_t::bjdata:
9429 result = parse_ubjson_internal();
9430 break;
9431
9432 case input_format_t::json: // LCOV_EXCL_LINE
9433 default: // LCOV_EXCL_LINE
9434 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9435 }
9436
9437 // strict mode: next byte must be EOF
9438 if (result && strict)
9439 {
9440 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9441 {
9442 get_ignore_noop();
9443 }
9444 else
9445 {
9446 get();
9447 }
9448
9450 {
9451 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9452 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9453 }
9454 }
9455
9456 return result;
9457 }
9458
9459 private:
9461 // BSON //
9463
9468 bool parse_bson_internal()
9469 {
9470 std::int32_t document_size{};
9471 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9472
9473 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9474 {
9475 return false;
9476 }
9477
9478 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9479 {
9480 return false;
9481 }
9482
9483 return sax->end_object();
9484 }
9485
9493 bool get_bson_cstr(string_t& result)
9494 {
9495 auto out = std::back_inserter(result);
9496 while (true)
9497 {
9498 get();
9499 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9500 {
9501 return false;
9502 }
9503 if (current == 0x00)
9504 {
9505 return true;
9506 }
9507 *out++ = static_cast<typename string_t::value_type>(current);
9508 }
9509 }
9510
9522 template<typename NumberType>
9523 bool get_bson_string(const NumberType len, string_t& result)
9524 {
9525 if (JSON_HEDLEY_UNLIKELY(len < 1))
9526 {
9527 auto last_token = get_token_string();
9528 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9529 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9530 }
9531
9532 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9533 }
9534
9544 template<typename NumberType>
9545 bool get_bson_binary(const NumberType len, binary_t& result)
9546 {
9547 if (JSON_HEDLEY_UNLIKELY(len < 0))
9548 {
9549 auto last_token = get_token_string();
9550 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9551 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9552 }
9553
9554 // All BSON binary values have a subtype
9555 std::uint8_t subtype{};
9556 get_number<std::uint8_t>(input_format_t::bson, subtype);
9557 result.set_subtype(subtype);
9558
9559 return get_binary(input_format_t::bson, len, result);
9560 }
9561
9572 bool parse_bson_element_internal(const char_int_type element_type,
9573 const std::size_t element_type_parse_position)
9574 {
9575 switch (element_type)
9576 {
9577 case 0x01: // double
9578 {
9579 double number{};
9580 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9581 }
9582
9583 case 0x02: // string
9584 {
9585 std::int32_t len{};
9586 string_t value;
9587 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9588 }
9589
9590 case 0x03: // object
9591 {
9592 return parse_bson_internal();
9593 }
9594
9595 case 0x04: // array
9596 {
9597 return parse_bson_array();
9598 }
9599
9600 case 0x05: // binary
9601 {
9602 std::int32_t len{};
9603 binary_t value;
9604 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9605 }
9606
9607 case 0x08: // boolean
9608 {
9609 return sax->boolean(get() != 0);
9610 }
9611
9612 case 0x0A: // null
9613 {
9614 return sax->null();
9615 }
9616
9617 case 0x10: // int32
9618 {
9619 std::int32_t value{};
9620 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9621 }
9622
9623 case 0x12: // int64
9624 {
9625 std::int64_t value{};
9626 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9627 }
9628
9629 default: // anything else not supported (yet)
9630 {
9631 std::array<char, 3> cr{{}};
9632 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9633 const std::string cr_str{cr.data()};
9634 return sax->parse_error(element_type_parse_position, cr_str,
9635 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9636 }
9637 }
9638 }
9639
9652 bool parse_bson_element_list(const bool is_array)
9653 {
9654 string_t key;
9655
9656 while (auto element_type = get())
9657 {
9658 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9659 {
9660 return false;
9661 }
9662
9663 const std::size_t element_type_parse_position = chars_read;
9664 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9665 {
9666 return false;
9667 }
9668
9669 if (!is_array && !sax->key(key))
9670 {
9671 return false;
9672 }
9673
9674 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9675 {
9676 return false;
9677 }
9678
9679 // get_bson_cstr only appends
9680 key.clear();
9681 }
9682
9683 return true;
9684 }
9685
9690 bool parse_bson_array()
9691 {
9692 std::int32_t document_size{};
9693 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9694
9695 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9696 {
9697 return false;
9698 }
9699
9700 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9701 {
9702 return false;
9703 }
9704
9705 return sax->end_array();
9706 }
9707
9709 // CBOR //
9711
9720 bool parse_cbor_internal(const bool get_char,
9721 const cbor_tag_handler_t tag_handler)
9722 {
9723 switch (get_char ? get() : current)
9724 {
9725 // EOF
9726 case char_traits<char_type>::eof():
9727 return unexpect_eof(input_format_t::cbor, "value");
9728
9729 // Integer 0x00..0x17 (0..23)
9730 case 0x00:
9731 case 0x01:
9732 case 0x02:
9733 case 0x03:
9734 case 0x04:
9735 case 0x05:
9736 case 0x06:
9737 case 0x07:
9738 case 0x08:
9739 case 0x09:
9740 case 0x0A:
9741 case 0x0B:
9742 case 0x0C:
9743 case 0x0D:
9744 case 0x0E:
9745 case 0x0F:
9746 case 0x10:
9747 case 0x11:
9748 case 0x12:
9749 case 0x13:
9750 case 0x14:
9751 case 0x15:
9752 case 0x16:
9753 case 0x17:
9754 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9755
9756 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9757 {
9758 std::uint8_t number{};
9759 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9760 }
9761
9762 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9763 {
9764 std::uint16_t number{};
9765 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9766 }
9767
9768 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9769 {
9770 std::uint32_t number{};
9771 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9772 }
9773
9774 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9775 {
9776 std::uint64_t number{};
9777 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9778 }
9779
9780 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9781 case 0x20:
9782 case 0x21:
9783 case 0x22:
9784 case 0x23:
9785 case 0x24:
9786 case 0x25:
9787 case 0x26:
9788 case 0x27:
9789 case 0x28:
9790 case 0x29:
9791 case 0x2A:
9792 case 0x2B:
9793 case 0x2C:
9794 case 0x2D:
9795 case 0x2E:
9796 case 0x2F:
9797 case 0x30:
9798 case 0x31:
9799 case 0x32:
9800 case 0x33:
9801 case 0x34:
9802 case 0x35:
9803 case 0x36:
9804 case 0x37:
9805 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9806
9807 case 0x38: // Negative integer (one-byte uint8_t follows)
9808 {
9809 std::uint8_t number{};
9810 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9811 }
9812
9813 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9814 {
9815 std::uint16_t number{};
9816 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9817 }
9818
9819 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9820 {
9821 std::uint32_t number{};
9822 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9823 }
9824
9825 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9826 {
9827 std::uint64_t number{};
9828 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9829 - static_cast<number_integer_t>(number));
9830 }
9831
9832 // Binary data (0x00..0x17 bytes follow)
9833 case 0x40:
9834 case 0x41:
9835 case 0x42:
9836 case 0x43:
9837 case 0x44:
9838 case 0x45:
9839 case 0x46:
9840 case 0x47:
9841 case 0x48:
9842 case 0x49:
9843 case 0x4A:
9844 case 0x4B:
9845 case 0x4C:
9846 case 0x4D:
9847 case 0x4E:
9848 case 0x4F:
9849 case 0x50:
9850 case 0x51:
9851 case 0x52:
9852 case 0x53:
9853 case 0x54:
9854 case 0x55:
9855 case 0x56:
9856 case 0x57:
9857 case 0x58: // Binary data (one-byte uint8_t for n follows)
9858 case 0x59: // Binary data (two-byte uint16_t for n follow)
9859 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9860 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9861 case 0x5F: // Binary data (indefinite length)
9862 {
9863 binary_t b;
9864 return get_cbor_binary(b) && sax->binary(b);
9865 }
9866
9867 // UTF-8 string (0x00..0x17 bytes follow)
9868 case 0x60:
9869 case 0x61:
9870 case 0x62:
9871 case 0x63:
9872 case 0x64:
9873 case 0x65:
9874 case 0x66:
9875 case 0x67:
9876 case 0x68:
9877 case 0x69:
9878 case 0x6A:
9879 case 0x6B:
9880 case 0x6C:
9881 case 0x6D:
9882 case 0x6E:
9883 case 0x6F:
9884 case 0x70:
9885 case 0x71:
9886 case 0x72:
9887 case 0x73:
9888 case 0x74:
9889 case 0x75:
9890 case 0x76:
9891 case 0x77:
9892 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9893 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9894 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9895 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9896 case 0x7F: // UTF-8 string (indefinite length)
9897 {
9898 string_t s;
9899 return get_cbor_string(s) && sax->string(s);
9900 }
9901
9902 // array (0x00..0x17 data items follow)
9903 case 0x80:
9904 case 0x81:
9905 case 0x82:
9906 case 0x83:
9907 case 0x84:
9908 case 0x85:
9909 case 0x86:
9910 case 0x87:
9911 case 0x88:
9912 case 0x89:
9913 case 0x8A:
9914 case 0x8B:
9915 case 0x8C:
9916 case 0x8D:
9917 case 0x8E:
9918 case 0x8F:
9919 case 0x90:
9920 case 0x91:
9921 case 0x92:
9922 case 0x93:
9923 case 0x94:
9924 case 0x95:
9925 case 0x96:
9926 case 0x97:
9927 return get_cbor_array(
9928 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9929
9930 case 0x98: // array (one-byte uint8_t for n follows)
9931 {
9932 std::uint8_t len{};
9933 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9934 }
9935
9936 case 0x99: // array (two-byte uint16_t for n follow)
9937 {
9938 std::uint16_t len{};
9939 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9940 }
9941
9942 case 0x9A: // array (four-byte uint32_t for n follow)
9943 {
9944 std::uint32_t len{};
9945 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9946 }
9947
9948 case 0x9B: // array (eight-byte uint64_t for n follow)
9949 {
9950 std::uint64_t len{};
9951 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9952 }
9953
9954 case 0x9F: // array (indefinite length)
9955 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9956
9957 // map (0x00..0x17 pairs of data items follow)
9958 case 0xA0:
9959 case 0xA1:
9960 case 0xA2:
9961 case 0xA3:
9962 case 0xA4:
9963 case 0xA5:
9964 case 0xA6:
9965 case 0xA7:
9966 case 0xA8:
9967 case 0xA9:
9968 case 0xAA:
9969 case 0xAB:
9970 case 0xAC:
9971 case 0xAD:
9972 case 0xAE:
9973 case 0xAF:
9974 case 0xB0:
9975 case 0xB1:
9976 case 0xB2:
9977 case 0xB3:
9978 case 0xB4:
9979 case 0xB5:
9980 case 0xB6:
9981 case 0xB7:
9982 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9983
9984 case 0xB8: // map (one-byte uint8_t for n follows)
9985 {
9986 std::uint8_t len{};
9987 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9988 }
9989
9990 case 0xB9: // map (two-byte uint16_t for n follow)
9991 {
9992 std::uint16_t len{};
9993 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9994 }
9995
9996 case 0xBA: // map (four-byte uint32_t for n follow)
9997 {
9998 std::uint32_t len{};
9999 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10000 }
10001
10002 case 0xBB: // map (eight-byte uint64_t for n follow)
10003 {
10004 std::uint64_t len{};
10005 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10006 }
10007
10008 case 0xBF: // map (indefinite length)
10009 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
10010
10011 case 0xC6: // tagged item
10012 case 0xC7:
10013 case 0xC8:
10014 case 0xC9:
10015 case 0xCA:
10016 case 0xCB:
10017 case 0xCC:
10018 case 0xCD:
10019 case 0xCE:
10020 case 0xCF:
10021 case 0xD0:
10022 case 0xD1:
10023 case 0xD2:
10024 case 0xD3:
10025 case 0xD4:
10026 case 0xD8: // tagged item (1 bytes follow)
10027 case 0xD9: // tagged item (2 bytes follow)
10028 case 0xDA: // tagged item (4 bytes follow)
10029 case 0xDB: // tagged item (8 bytes follow)
10030 {
10031 switch (tag_handler)
10032 {
10034 {
10035 auto last_token = get_token_string();
10036 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10037 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10038 }
10039
10041 {
10042 // ignore binary subtype
10043 switch (current)
10044 {
10045 case 0xD8:
10046 {
10047 std::uint8_t subtype_to_ignore{};
10048 get_number(input_format_t::cbor, subtype_to_ignore);
10049 break;
10050 }
10051 case 0xD9:
10052 {
10053 std::uint16_t subtype_to_ignore{};
10054 get_number(input_format_t::cbor, subtype_to_ignore);
10055 break;
10056 }
10057 case 0xDA:
10058 {
10059 std::uint32_t subtype_to_ignore{};
10060 get_number(input_format_t::cbor, subtype_to_ignore);
10061 break;
10062 }
10063 case 0xDB:
10064 {
10065 std::uint64_t subtype_to_ignore{};
10066 get_number(input_format_t::cbor, subtype_to_ignore);
10067 break;
10068 }
10069 default:
10070 break;
10071 }
10072 return parse_cbor_internal(true, tag_handler);
10073 }
10074
10076 {
10077 binary_t b;
10078 // use binary subtype and store in binary container
10079 switch (current)
10080 {
10081 case 0xD8:
10082 {
10083 std::uint8_t subtype{};
10084 get_number(input_format_t::cbor, subtype);
10085 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10086 break;
10087 }
10088 case 0xD9:
10089 {
10090 std::uint16_t subtype{};
10091 get_number(input_format_t::cbor, subtype);
10092 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10093 break;
10094 }
10095 case 0xDA:
10096 {
10097 std::uint32_t subtype{};
10098 get_number(input_format_t::cbor, subtype);
10099 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10100 break;
10101 }
10102 case 0xDB:
10103 {
10104 std::uint64_t subtype{};
10105 get_number(input_format_t::cbor, subtype);
10106 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10107 break;
10108 }
10109 default:
10110 return parse_cbor_internal(true, tag_handler);
10111 }
10112 get();
10113 return get_cbor_binary(b) && sax->binary(b);
10114 }
10115
10116 default: // LCOV_EXCL_LINE
10117 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10118 return false; // LCOV_EXCL_LINE
10119 }
10120 }
10121
10122 case 0xF4: // false
10123 return sax->boolean(false);
10124
10125 case 0xF5: // true
10126 return sax->boolean(true);
10127
10128 case 0xF6: // null
10129 return sax->null();
10130
10131 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10132 {
10133 const auto byte1_raw = get();
10134 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10135 {
10136 return false;
10137 }
10138 const auto byte2_raw = get();
10139 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10140 {
10141 return false;
10142 }
10143
10144 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10145 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10146
10147 // code from RFC 7049, Appendix D, Figure 3:
10148 // As half-precision floating-point numbers were only added
10149 // to IEEE 754 in 2008, today's programming platforms often
10150 // still only have limited support for them. It is very
10151 // easy to include at least decoding support for them even
10152 // without such support. An example of a small decoder for
10153 // half-precision floating-point numbers in the C language
10154 // is shown in Fig. 3.
10155 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10156 const double val = [&half]
10157 {
10158 const int exp = (half >> 10u) & 0x1Fu;
10159 const unsigned int mant = half & 0x3FFu;
10160 JSON_ASSERT(0 <= exp&& exp <= 32);
10161 JSON_ASSERT(mant <= 1024);
10162 switch (exp)
10163 {
10164 case 0:
10165 return std::ldexp(mant, -24);
10166 case 31:
10167 return (mant == 0)
10168 ? std::numeric_limits<double>::infinity()
10169 : std::numeric_limits<double>::quiet_NaN();
10170 default:
10171 return std::ldexp(mant + 1024, exp - 25);
10172 }
10173 }();
10174 return sax->number_float((half & 0x8000u) != 0
10175 ? static_cast<number_float_t>(-val)
10176 : static_cast<number_float_t>(val), "");
10177 }
10178
10179 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10180 {
10181 float number{};
10182 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10183 }
10184
10185 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10186 {
10187 double number{};
10188 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10189 }
10190
10191 default: // anything else (0xFF is handled inside the other types)
10192 {
10193 auto last_token = get_token_string();
10194 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10195 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10196 }
10197 }
10198 }
10199
10211 bool get_cbor_string(string_t& result)
10212 {
10213 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10214 {
10215 return false;
10216 }
10217
10218 switch (current)
10219 {
10220 // UTF-8 string (0x00..0x17 bytes follow)
10221 case 0x60:
10222 case 0x61:
10223 case 0x62:
10224 case 0x63:
10225 case 0x64:
10226 case 0x65:
10227 case 0x66:
10228 case 0x67:
10229 case 0x68:
10230 case 0x69:
10231 case 0x6A:
10232 case 0x6B:
10233 case 0x6C:
10234 case 0x6D:
10235 case 0x6E:
10236 case 0x6F:
10237 case 0x70:
10238 case 0x71:
10239 case 0x72:
10240 case 0x73:
10241 case 0x74:
10242 case 0x75:
10243 case 0x76:
10244 case 0x77:
10245 {
10246 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10247 }
10248
10249 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10250 {
10251 std::uint8_t len{};
10252 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10253 }
10254
10255 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10256 {
10257 std::uint16_t len{};
10258 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10259 }
10260
10261 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10262 {
10263 std::uint32_t len{};
10264 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10265 }
10266
10267 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10268 {
10269 std::uint64_t len{};
10270 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10271 }
10272
10273 case 0x7F: // UTF-8 string (indefinite length)
10274 {
10275 while (get() != 0xFF)
10276 {
10277 string_t chunk;
10278 if (!get_cbor_string(chunk))
10279 {
10280 return false;
10281 }
10282 result.append(chunk);
10283 }
10284 return true;
10285 }
10286
10287 default:
10288 {
10289 auto last_token = get_token_string();
10290 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10291 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10292 }
10293 }
10294 }
10295
10307 bool get_cbor_binary(binary_t& result)
10308 {
10309 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10310 {
10311 return false;
10312 }
10313
10314 switch (current)
10315 {
10316 // Binary data (0x00..0x17 bytes follow)
10317 case 0x40:
10318 case 0x41:
10319 case 0x42:
10320 case 0x43:
10321 case 0x44:
10322 case 0x45:
10323 case 0x46:
10324 case 0x47:
10325 case 0x48:
10326 case 0x49:
10327 case 0x4A:
10328 case 0x4B:
10329 case 0x4C:
10330 case 0x4D:
10331 case 0x4E:
10332 case 0x4F:
10333 case 0x50:
10334 case 0x51:
10335 case 0x52:
10336 case 0x53:
10337 case 0x54:
10338 case 0x55:
10339 case 0x56:
10340 case 0x57:
10341 {
10342 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10343 }
10344
10345 case 0x58: // Binary data (one-byte uint8_t for n follows)
10346 {
10347 std::uint8_t len{};
10348 return get_number(input_format_t::cbor, len) &&
10349 get_binary(input_format_t::cbor, len, result);
10350 }
10351
10352 case 0x59: // Binary data (two-byte uint16_t for n follow)
10353 {
10354 std::uint16_t len{};
10355 return get_number(input_format_t::cbor, len) &&
10356 get_binary(input_format_t::cbor, len, result);
10357 }
10358
10359 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10360 {
10361 std::uint32_t len{};
10362 return get_number(input_format_t::cbor, len) &&
10363 get_binary(input_format_t::cbor, len, result);
10364 }
10365
10366 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10367 {
10368 std::uint64_t len{};
10369 return get_number(input_format_t::cbor, len) &&
10370 get_binary(input_format_t::cbor, len, result);
10371 }
10372
10373 case 0x5F: // Binary data (indefinite length)
10374 {
10375 while (get() != 0xFF)
10376 {
10377 binary_t chunk;
10378 if (!get_cbor_binary(chunk))
10379 {
10380 return false;
10381 }
10382 result.insert(result.end(), chunk.begin(), chunk.end());
10383 }
10384 return true;
10385 }
10386
10387 default:
10388 {
10389 auto last_token = get_token_string();
10390 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10391 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10392 }
10393 }
10394 }
10395
10402 bool get_cbor_array(const std::size_t len,
10403 const cbor_tag_handler_t tag_handler)
10404 {
10405 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10406 {
10407 return false;
10408 }
10409
10410 if (len != static_cast<std::size_t>(-1))
10411 {
10412 for (std::size_t i = 0; i < len; ++i)
10413 {
10414 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10415 {
10416 return false;
10417 }
10418 }
10419 }
10420 else
10421 {
10422 while (get() != 0xFF)
10423 {
10424 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10425 {
10426 return false;
10427 }
10428 }
10429 }
10430
10431 return sax->end_array();
10432 }
10433
10440 bool get_cbor_object(const std::size_t len,
10441 const cbor_tag_handler_t tag_handler)
10442 {
10443 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10444 {
10445 return false;
10446 }
10447
10448 if (len != 0)
10449 {
10450 string_t key;
10451 if (len != static_cast<std::size_t>(-1))
10452 {
10453 for (std::size_t i = 0; i < len; ++i)
10454 {
10455 get();
10456 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10457 {
10458 return false;
10459 }
10460
10461 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10462 {
10463 return false;
10464 }
10465 key.clear();
10466 }
10467 }
10468 else
10469 {
10470 while (get() != 0xFF)
10471 {
10472 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10473 {
10474 return false;
10475 }
10476
10477 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10478 {
10479 return false;
10480 }
10481 key.clear();
10482 }
10483 }
10484 }
10485
10486 return sax->end_object();
10487 }
10488
10490 // MsgPack //
10492
10496 bool parse_msgpack_internal()
10497 {
10498 switch (get())
10499 {
10500 // EOF
10501 case char_traits<char_type>::eof():
10502 return unexpect_eof(input_format_t::msgpack, "value");
10503
10504 // positive fixint
10505 case 0x00:
10506 case 0x01:
10507 case 0x02:
10508 case 0x03:
10509 case 0x04:
10510 case 0x05:
10511 case 0x06:
10512 case 0x07:
10513 case 0x08:
10514 case 0x09:
10515 case 0x0A:
10516 case 0x0B:
10517 case 0x0C:
10518 case 0x0D:
10519 case 0x0E:
10520 case 0x0F:
10521 case 0x10:
10522 case 0x11:
10523 case 0x12:
10524 case 0x13:
10525 case 0x14:
10526 case 0x15:
10527 case 0x16:
10528 case 0x17:
10529 case 0x18:
10530 case 0x19:
10531 case 0x1A:
10532 case 0x1B:
10533 case 0x1C:
10534 case 0x1D:
10535 case 0x1E:
10536 case 0x1F:
10537 case 0x20:
10538 case 0x21:
10539 case 0x22:
10540 case 0x23:
10541 case 0x24:
10542 case 0x25:
10543 case 0x26:
10544 case 0x27:
10545 case 0x28:
10546 case 0x29:
10547 case 0x2A:
10548 case 0x2B:
10549 case 0x2C:
10550 case 0x2D:
10551 case 0x2E:
10552 case 0x2F:
10553 case 0x30:
10554 case 0x31:
10555 case 0x32:
10556 case 0x33:
10557 case 0x34:
10558 case 0x35:
10559 case 0x36:
10560 case 0x37:
10561 case 0x38:
10562 case 0x39:
10563 case 0x3A:
10564 case 0x3B:
10565 case 0x3C:
10566 case 0x3D:
10567 case 0x3E:
10568 case 0x3F:
10569 case 0x40:
10570 case 0x41:
10571 case 0x42:
10572 case 0x43:
10573 case 0x44:
10574 case 0x45:
10575 case 0x46:
10576 case 0x47:
10577 case 0x48:
10578 case 0x49:
10579 case 0x4A:
10580 case 0x4B:
10581 case 0x4C:
10582 case 0x4D:
10583 case 0x4E:
10584 case 0x4F:
10585 case 0x50:
10586 case 0x51:
10587 case 0x52:
10588 case 0x53:
10589 case 0x54:
10590 case 0x55:
10591 case 0x56:
10592 case 0x57:
10593 case 0x58:
10594 case 0x59:
10595 case 0x5A:
10596 case 0x5B:
10597 case 0x5C:
10598 case 0x5D:
10599 case 0x5E:
10600 case 0x5F:
10601 case 0x60:
10602 case 0x61:
10603 case 0x62:
10604 case 0x63:
10605 case 0x64:
10606 case 0x65:
10607 case 0x66:
10608 case 0x67:
10609 case 0x68:
10610 case 0x69:
10611 case 0x6A:
10612 case 0x6B:
10613 case 0x6C:
10614 case 0x6D:
10615 case 0x6E:
10616 case 0x6F:
10617 case 0x70:
10618 case 0x71:
10619 case 0x72:
10620 case 0x73:
10621 case 0x74:
10622 case 0x75:
10623 case 0x76:
10624 case 0x77:
10625 case 0x78:
10626 case 0x79:
10627 case 0x7A:
10628 case 0x7B:
10629 case 0x7C:
10630 case 0x7D:
10631 case 0x7E:
10632 case 0x7F:
10633 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10634
10635 // fixmap
10636 case 0x80:
10637 case 0x81:
10638 case 0x82:
10639 case 0x83:
10640 case 0x84:
10641 case 0x85:
10642 case 0x86:
10643 case 0x87:
10644 case 0x88:
10645 case 0x89:
10646 case 0x8A:
10647 case 0x8B:
10648 case 0x8C:
10649 case 0x8D:
10650 case 0x8E:
10651 case 0x8F:
10652 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10653
10654 // fixarray
10655 case 0x90:
10656 case 0x91:
10657 case 0x92:
10658 case 0x93:
10659 case 0x94:
10660 case 0x95:
10661 case 0x96:
10662 case 0x97:
10663 case 0x98:
10664 case 0x99:
10665 case 0x9A:
10666 case 0x9B:
10667 case 0x9C:
10668 case 0x9D:
10669 case 0x9E:
10670 case 0x9F:
10671 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10672
10673 // fixstr
10674 case 0xA0:
10675 case 0xA1:
10676 case 0xA2:
10677 case 0xA3:
10678 case 0xA4:
10679 case 0xA5:
10680 case 0xA6:
10681 case 0xA7:
10682 case 0xA8:
10683 case 0xA9:
10684 case 0xAA:
10685 case 0xAB:
10686 case 0xAC:
10687 case 0xAD:
10688 case 0xAE:
10689 case 0xAF:
10690 case 0xB0:
10691 case 0xB1:
10692 case 0xB2:
10693 case 0xB3:
10694 case 0xB4:
10695 case 0xB5:
10696 case 0xB6:
10697 case 0xB7:
10698 case 0xB8:
10699 case 0xB9:
10700 case 0xBA:
10701 case 0xBB:
10702 case 0xBC:
10703 case 0xBD:
10704 case 0xBE:
10705 case 0xBF:
10706 case 0xD9: // str 8
10707 case 0xDA: // str 16
10708 case 0xDB: // str 32
10709 {
10710 string_t s;
10711 return get_msgpack_string(s) && sax->string(s);
10712 }
10713
10714 case 0xC0: // nil
10715 return sax->null();
10716
10717 case 0xC2: // false
10718 return sax->boolean(false);
10719
10720 case 0xC3: // true
10721 return sax->boolean(true);
10722
10723 case 0xC4: // bin 8
10724 case 0xC5: // bin 16
10725 case 0xC6: // bin 32
10726 case 0xC7: // ext 8
10727 case 0xC8: // ext 16
10728 case 0xC9: // ext 32
10729 case 0xD4: // fixext 1
10730 case 0xD5: // fixext 2
10731 case 0xD6: // fixext 4
10732 case 0xD7: // fixext 8
10733 case 0xD8: // fixext 16
10734 {
10735 binary_t b;
10736 return get_msgpack_binary(b) && sax->binary(b);
10737 }
10738
10739 case 0xCA: // float 32
10740 {
10741 float number{};
10742 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10743 }
10744
10745 case 0xCB: // float 64
10746 {
10747 double number{};
10748 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10749 }
10750
10751 case 0xCC: // uint 8
10752 {
10753 std::uint8_t number{};
10754 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10755 }
10756
10757 case 0xCD: // uint 16
10758 {
10759 std::uint16_t number{};
10760 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10761 }
10762
10763 case 0xCE: // uint 32
10764 {
10765 std::uint32_t number{};
10766 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10767 }
10768
10769 case 0xCF: // uint 64
10770 {
10771 std::uint64_t number{};
10772 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10773 }
10774
10775 case 0xD0: // int 8
10776 {
10777 std::int8_t number{};
10778 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10779 }
10780
10781 case 0xD1: // int 16
10782 {
10783 std::int16_t number{};
10784 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10785 }
10786
10787 case 0xD2: // int 32
10788 {
10789 std::int32_t number{};
10790 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10791 }
10792
10793 case 0xD3: // int 64
10794 {
10795 std::int64_t number{};
10796 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10797 }
10798
10799 case 0xDC: // array 16
10800 {
10801 std::uint16_t len{};
10802 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10803 }
10804
10805 case 0xDD: // array 32
10806 {
10807 std::uint32_t len{};
10808 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10809 }
10810
10811 case 0xDE: // map 16
10812 {
10813 std::uint16_t len{};
10814 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10815 }
10816
10817 case 0xDF: // map 32
10818 {
10819 std::uint32_t len{};
10820 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10821 }
10822
10823 // negative fixint
10824 case 0xE0:
10825 case 0xE1:
10826 case 0xE2:
10827 case 0xE3:
10828 case 0xE4:
10829 case 0xE5:
10830 case 0xE6:
10831 case 0xE7:
10832 case 0xE8:
10833 case 0xE9:
10834 case 0xEA:
10835 case 0xEB:
10836 case 0xEC:
10837 case 0xED:
10838 case 0xEE:
10839 case 0xEF:
10840 case 0xF0:
10841 case 0xF1:
10842 case 0xF2:
10843 case 0xF3:
10844 case 0xF4:
10845 case 0xF5:
10846 case 0xF6:
10847 case 0xF7:
10848 case 0xF8:
10849 case 0xF9:
10850 case 0xFA:
10851 case 0xFB:
10852 case 0xFC:
10853 case 0xFD:
10854 case 0xFE:
10855 case 0xFF:
10856 return sax->number_integer(static_cast<std::int8_t>(current));
10857
10858 default: // anything else
10859 {
10860 auto last_token = get_token_string();
10861 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10862 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10863 }
10864 }
10865 }
10866
10877 bool get_msgpack_string(string_t& result)
10878 {
10879 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10880 {
10881 return false;
10882 }
10883
10884 switch (current)
10885 {
10886 // fixstr
10887 case 0xA0:
10888 case 0xA1:
10889 case 0xA2:
10890 case 0xA3:
10891 case 0xA4:
10892 case 0xA5:
10893 case 0xA6:
10894 case 0xA7:
10895 case 0xA8:
10896 case 0xA9:
10897 case 0xAA:
10898 case 0xAB:
10899 case 0xAC:
10900 case 0xAD:
10901 case 0xAE:
10902 case 0xAF:
10903 case 0xB0:
10904 case 0xB1:
10905 case 0xB2:
10906 case 0xB3:
10907 case 0xB4:
10908 case 0xB5:
10909 case 0xB6:
10910 case 0xB7:
10911 case 0xB8:
10912 case 0xB9:
10913 case 0xBA:
10914 case 0xBB:
10915 case 0xBC:
10916 case 0xBD:
10917 case 0xBE:
10918 case 0xBF:
10919 {
10920 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10921 }
10922
10923 case 0xD9: // str 8
10924 {
10925 std::uint8_t len{};
10926 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10927 }
10928
10929 case 0xDA: // str 16
10930 {
10931 std::uint16_t len{};
10932 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10933 }
10934
10935 case 0xDB: // str 32
10936 {
10937 std::uint32_t len{};
10938 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10939 }
10940
10941 default:
10942 {
10943 auto last_token = get_token_string();
10944 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10945 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10946 }
10947 }
10948 }
10949
10960 bool get_msgpack_binary(binary_t& result)
10961 {
10962 // helper function to set the subtype
10963 auto assign_and_return_true = [&result](std::int8_t subtype)
10964 {
10965 result.set_subtype(static_cast<std::uint8_t>(subtype));
10966 return true;
10967 };
10968
10969 switch (current)
10970 {
10971 case 0xC4: // bin 8
10972 {
10973 std::uint8_t len{};
10974 return get_number(input_format_t::msgpack, len) &&
10975 get_binary(input_format_t::msgpack, len, result);
10976 }
10977
10978 case 0xC5: // bin 16
10979 {
10980 std::uint16_t len{};
10981 return get_number(input_format_t::msgpack, len) &&
10982 get_binary(input_format_t::msgpack, len, result);
10983 }
10984
10985 case 0xC6: // bin 32
10986 {
10987 std::uint32_t len{};
10988 return get_number(input_format_t::msgpack, len) &&
10989 get_binary(input_format_t::msgpack, len, result);
10990 }
10991
10992 case 0xC7: // ext 8
10993 {
10994 std::uint8_t len{};
10995 std::int8_t subtype{};
10996 return get_number(input_format_t::msgpack, len) &&
10997 get_number(input_format_t::msgpack, subtype) &&
10998 get_binary(input_format_t::msgpack, len, result) &&
10999 assign_and_return_true(subtype);
11000 }
11001
11002 case 0xC8: // ext 16
11003 {
11004 std::uint16_t len{};
11005 std::int8_t subtype{};
11006 return get_number(input_format_t::msgpack, len) &&
11007 get_number(input_format_t::msgpack, subtype) &&
11008 get_binary(input_format_t::msgpack, len, result) &&
11009 assign_and_return_true(subtype);
11010 }
11011
11012 case 0xC9: // ext 32
11013 {
11014 std::uint32_t len{};
11015 std::int8_t subtype{};
11016 return get_number(input_format_t::msgpack, len) &&
11017 get_number(input_format_t::msgpack, subtype) &&
11018 get_binary(input_format_t::msgpack, len, result) &&
11019 assign_and_return_true(subtype);
11020 }
11021
11022 case 0xD4: // fixext 1
11023 {
11024 std::int8_t subtype{};
11025 return get_number(input_format_t::msgpack, subtype) &&
11026 get_binary(input_format_t::msgpack, 1, result) &&
11027 assign_and_return_true(subtype);
11028 }
11029
11030 case 0xD5: // fixext 2
11031 {
11032 std::int8_t subtype{};
11033 return get_number(input_format_t::msgpack, subtype) &&
11034 get_binary(input_format_t::msgpack, 2, result) &&
11035 assign_and_return_true(subtype);
11036 }
11037
11038 case 0xD6: // fixext 4
11039 {
11040 std::int8_t subtype{};
11041 return get_number(input_format_t::msgpack, subtype) &&
11042 get_binary(input_format_t::msgpack, 4, result) &&
11043 assign_and_return_true(subtype);
11044 }
11045
11046 case 0xD7: // fixext 8
11047 {
11048 std::int8_t subtype{};
11049 return get_number(input_format_t::msgpack, subtype) &&
11050 get_binary(input_format_t::msgpack, 8, result) &&
11051 assign_and_return_true(subtype);
11052 }
11053
11054 case 0xD8: // fixext 16
11055 {
11056 std::int8_t subtype{};
11057 return get_number(input_format_t::msgpack, subtype) &&
11058 get_binary(input_format_t::msgpack, 16, result) &&
11059 assign_and_return_true(subtype);
11060 }
11061
11062 default: // LCOV_EXCL_LINE
11063 return false; // LCOV_EXCL_LINE
11064 }
11065 }
11066
11071 bool get_msgpack_array(const std::size_t len)
11072 {
11073 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11074 {
11075 return false;
11076 }
11077
11078 for (std::size_t i = 0; i < len; ++i)
11079 {
11080 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11081 {
11082 return false;
11083 }
11084 }
11085
11086 return sax->end_array();
11087 }
11088
11093 bool get_msgpack_object(const std::size_t len)
11094 {
11095 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11096 {
11097 return false;
11098 }
11099
11100 string_t key;
11101 for (std::size_t i = 0; i < len; ++i)
11102 {
11103 get();
11104 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11105 {
11106 return false;
11107 }
11108
11109 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11110 {
11111 return false;
11112 }
11113 key.clear();
11114 }
11115
11116 return sax->end_object();
11117 }
11118
11120 // UBJSON //
11122
11130 bool parse_ubjson_internal(const bool get_char = true)
11131 {
11132 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11133 }
11134
11149 bool get_ubjson_string(string_t& result, const bool get_char = true)
11150 {
11151 if (get_char)
11152 {
11153 get(); // TODO(niels): may we ignore N here?
11154 }
11155
11156 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11157 {
11158 return false;
11159 }
11160
11161 switch (current)
11162 {
11163 case 'U':
11164 {
11165 std::uint8_t len{};
11166 return get_number(input_format, len) && get_string(input_format, len, result);
11167 }
11168
11169 case 'i':
11170 {
11171 std::int8_t len{};
11172 return get_number(input_format, len) && get_string(input_format, len, result);
11173 }
11174
11175 case 'I':
11176 {
11177 std::int16_t len{};
11178 return get_number(input_format, len) && get_string(input_format, len, result);
11179 }
11180
11181 case 'l':
11182 {
11183 std::int32_t len{};
11184 return get_number(input_format, len) && get_string(input_format, len, result);
11185 }
11186
11187 case 'L':
11188 {
11189 std::int64_t len{};
11190 return get_number(input_format, len) && get_string(input_format, len, result);
11191 }
11192
11193 case 'u':
11194 {
11195 if (input_format != input_format_t::bjdata)
11196 {
11197 break;
11198 }
11199 std::uint16_t len{};
11200 return get_number(input_format, len) && get_string(input_format, len, result);
11201 }
11202
11203 case 'm':
11204 {
11205 if (input_format != input_format_t::bjdata)
11206 {
11207 break;
11208 }
11209 std::uint32_t len{};
11210 return get_number(input_format, len) && get_string(input_format, len, result);
11211 }
11212
11213 case 'M':
11214 {
11215 if (input_format != input_format_t::bjdata)
11216 {
11217 break;
11218 }
11219 std::uint64_t len{};
11220 return get_number(input_format, len) && get_string(input_format, len, result);
11221 }
11222
11223 default:
11224 break;
11225 }
11226 auto last_token = get_token_string();
11227 std::string message;
11228
11229 if (input_format != input_format_t::bjdata)
11230 {
11231 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11232 }
11233 else
11234 {
11235 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11236 }
11237 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11238 }
11239
11244 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11245 {
11246 std::pair<std::size_t, char_int_type> size_and_type;
11247 size_t dimlen = 0;
11248 bool no_ndarray = true;
11249
11250 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11251 {
11252 return false;
11253 }
11254
11255 if (size_and_type.first != npos)
11256 {
11257 if (size_and_type.second != 0)
11258 {
11259 if (size_and_type.second != 'N')
11260 {
11261 for (std::size_t i = 0; i < size_and_type.first; ++i)
11262 {
11263 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11264 {
11265 return false;
11266 }
11267 dim.push_back(dimlen);
11268 }
11269 }
11270 }
11271 else
11272 {
11273 for (std::size_t i = 0; i < size_and_type.first; ++i)
11274 {
11275 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11276 {
11277 return false;
11278 }
11279 dim.push_back(dimlen);
11280 }
11281 }
11282 }
11283 else
11284 {
11285 while (current != ']')
11286 {
11287 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11288 {
11289 return false;
11290 }
11291 dim.push_back(dimlen);
11292 get_ignore_noop();
11293 }
11294 }
11295 return true;
11296 }
11297
11309 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11310 {
11311 if (prefix == 0)
11312 {
11313 prefix = get_ignore_noop();
11314 }
11315
11316 switch (prefix)
11317 {
11318 case 'U':
11319 {
11320 std::uint8_t number{};
11321 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11322 {
11323 return false;
11324 }
11325 result = static_cast<std::size_t>(number);
11326 return true;
11327 }
11328
11329 case 'i':
11330 {
11331 std::int8_t number{};
11332 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11333 {
11334 return false;
11335 }
11336 if (number < 0)
11337 {
11338 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11339 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11340 }
11341 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11342 return true;
11343 }
11344
11345 case 'I':
11346 {
11347 std::int16_t number{};
11348 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11349 {
11350 return false;
11351 }
11352 if (number < 0)
11353 {
11354 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11355 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11356 }
11357 result = static_cast<std::size_t>(number);
11358 return true;
11359 }
11360
11361 case 'l':
11362 {
11363 std::int32_t number{};
11364 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11365 {
11366 return false;
11367 }
11368 if (number < 0)
11369 {
11370 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11371 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11372 }
11373 result = static_cast<std::size_t>(number);
11374 return true;
11375 }
11376
11377 case 'L':
11378 {
11379 std::int64_t number{};
11380 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11381 {
11382 return false;
11383 }
11384 if (number < 0)
11385 {
11386 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11387 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11388 }
11389 if (!value_in_range_of<std::size_t>(number))
11390 {
11391 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11392 exception_message(input_format, "integer value overflow", "size"), nullptr));
11393 }
11394 result = static_cast<std::size_t>(number);
11395 return true;
11396 }
11397
11398 case 'u':
11399 {
11400 if (input_format != input_format_t::bjdata)
11401 {
11402 break;
11403 }
11404 std::uint16_t number{};
11405 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11406 {
11407 return false;
11408 }
11409 result = static_cast<std::size_t>(number);
11410 return true;
11411 }
11412
11413 case 'm':
11414 {
11415 if (input_format != input_format_t::bjdata)
11416 {
11417 break;
11418 }
11419 std::uint32_t number{};
11420 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11421 {
11422 return false;
11423 }
11424 result = conditional_static_cast<std::size_t>(number);
11425 return true;
11426 }
11427
11428 case 'M':
11429 {
11430 if (input_format != input_format_t::bjdata)
11431 {
11432 break;
11433 }
11434 std::uint64_t number{};
11435 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11436 {
11437 return false;
11438 }
11439 if (!value_in_range_of<std::size_t>(number))
11440 {
11441 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11442 exception_message(input_format, "integer value overflow", "size"), nullptr));
11443 }
11444 result = detail::conditional_static_cast<std::size_t>(number);
11445 return true;
11446 }
11447
11448 case '[':
11449 {
11450 if (input_format != input_format_t::bjdata)
11451 {
11452 break;
11453 }
11454 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11455 {
11456 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11457 }
11458 std::vector<size_t> dim;
11459 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11460 {
11461 return false;
11462 }
11463 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11464 {
11465 result = dim.at(dim.size() - 1);
11466 return true;
11467 }
11468 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11469 {
11470 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11471 {
11472 if ( i == 0 )
11473 {
11474 result = 0;
11475 return true;
11476 }
11477 }
11478
11479 string_t key = "_ArraySize_";
11480 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11481 {
11482 return false;
11483 }
11484 result = 1;
11485 for (auto i : dim)
11486 {
11487 result *= i;
11488 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11489 {
11490 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
11491 }
11492 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11493 {
11494 return false;
11495 }
11496 }
11497 is_ndarray = true;
11498 return sax->end_array();
11499 }
11500 result = 0;
11501 return true;
11502 }
11503
11504 default:
11505 break;
11506 }
11507 auto last_token = get_token_string();
11508 std::string message;
11509
11510 if (input_format != input_format_t::bjdata)
11511 {
11512 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11513 }
11514 else
11515 {
11516 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11517 }
11518 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11519 }
11520
11532 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11533 {
11534 result.first = npos; // size
11535 result.second = 0; // type
11536 bool is_ndarray = false;
11537
11538 get_ignore_noop();
11539
11540 if (current == '$')
11541 {
11542 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11543 if (input_format == input_format_t::bjdata
11544 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11545 {
11546 auto last_token = get_token_string();
11547 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11548 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11549 }
11550
11551 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11552 {
11553 return false;
11554 }
11555
11556 get_ignore_noop();
11557 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11558 {
11559 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11560 {
11561 return false;
11562 }
11563 auto last_token = get_token_string();
11564 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11565 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11566 }
11567
11568 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11569 if (input_format == input_format_t::bjdata && is_ndarray)
11570 {
11571 if (inside_ndarray)
11572 {
11573 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11574 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11575 }
11576 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11577 }
11578 return is_error;
11579 }
11580
11581 if (current == '#')
11582 {
11583 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11584 if (input_format == input_format_t::bjdata && is_ndarray)
11585 {
11586 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11587 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11588 }
11589 return is_error;
11590 }
11591
11592 return true;
11593 }
11594
11599 bool get_ubjson_value(const char_int_type prefix)
11600 {
11601 switch (prefix)
11602 {
11603 case char_traits<char_type>::eof(): // EOF
11604 return unexpect_eof(input_format, "value");
11605
11606 case 'T': // true
11607 return sax->boolean(true);
11608 case 'F': // false
11609 return sax->boolean(false);
11610
11611 case 'Z': // null
11612 return sax->null();
11613
11614 case 'U':
11615 {
11616 std::uint8_t number{};
11617 return get_number(input_format, number) && sax->number_unsigned(number);
11618 }
11619
11620 case 'i':
11621 {
11622 std::int8_t number{};
11623 return get_number(input_format, number) && sax->number_integer(number);
11624 }
11625
11626 case 'I':
11627 {
11628 std::int16_t number{};
11629 return get_number(input_format, number) && sax->number_integer(number);
11630 }
11631
11632 case 'l':
11633 {
11634 std::int32_t number{};
11635 return get_number(input_format, number) && sax->number_integer(number);
11636 }
11637
11638 case 'L':
11639 {
11640 std::int64_t number{};
11641 return get_number(input_format, number) && sax->number_integer(number);
11642 }
11643
11644 case 'u':
11645 {
11646 if (input_format != input_format_t::bjdata)
11647 {
11648 break;
11649 }
11650 std::uint16_t number{};
11651 return get_number(input_format, number) && sax->number_unsigned(number);
11652 }
11653
11654 case 'm':
11655 {
11656 if (input_format != input_format_t::bjdata)
11657 {
11658 break;
11659 }
11660 std::uint32_t number{};
11661 return get_number(input_format, number) && sax->number_unsigned(number);
11662 }
11663
11664 case 'M':
11665 {
11666 if (input_format != input_format_t::bjdata)
11667 {
11668 break;
11669 }
11670 std::uint64_t number{};
11671 return get_number(input_format, number) && sax->number_unsigned(number);
11672 }
11673
11674 case 'h':
11675 {
11676 if (input_format != input_format_t::bjdata)
11677 {
11678 break;
11679 }
11680 const auto byte1_raw = get();
11681 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11682 {
11683 return false;
11684 }
11685 const auto byte2_raw = get();
11686 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11687 {
11688 return false;
11689 }
11690
11691 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11692 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11693
11694 // code from RFC 7049, Appendix D, Figure 3:
11695 // As half-precision floating-point numbers were only added
11696 // to IEEE 754 in 2008, today's programming platforms often
11697 // still only have limited support for them. It is very
11698 // easy to include at least decoding support for them even
11699 // without such support. An example of a small decoder for
11700 // half-precision floating-point numbers in the C language
11701 // is shown in Fig. 3.
11702 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11703 const double val = [&half]
11704 {
11705 const int exp = (half >> 10u) & 0x1Fu;
11706 const unsigned int mant = half & 0x3FFu;
11707 JSON_ASSERT(0 <= exp&& exp <= 32);
11708 JSON_ASSERT(mant <= 1024);
11709 switch (exp)
11710 {
11711 case 0:
11712 return std::ldexp(mant, -24);
11713 case 31:
11714 return (mant == 0)
11715 ? std::numeric_limits<double>::infinity()
11716 : std::numeric_limits<double>::quiet_NaN();
11717 default:
11718 return std::ldexp(mant + 1024, exp - 25);
11719 }
11720 }();
11721 return sax->number_float((half & 0x8000u) != 0
11722 ? static_cast<number_float_t>(-val)
11723 : static_cast<number_float_t>(val), "");
11724 }
11725
11726 case 'd':
11727 {
11728 float number{};
11729 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11730 }
11731
11732 case 'D':
11733 {
11734 double number{};
11735 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11736 }
11737
11738 case 'H':
11739 {
11740 return get_ubjson_high_precision_number();
11741 }
11742
11743 case 'C': // char
11744 {
11745 get();
11746 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11747 {
11748 return false;
11749 }
11750 if (JSON_HEDLEY_UNLIKELY(current > 127))
11751 {
11752 auto last_token = get_token_string();
11753 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11754 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11755 }
11756 string_t s(1, static_cast<typename string_t::value_type>(current));
11757 return sax->string(s);
11758 }
11759
11760 case 'S': // string
11761 {
11762 string_t s;
11763 return get_ubjson_string(s) && sax->string(s);
11764 }
11765
11766 case '[': // array
11767 return get_ubjson_array();
11768
11769 case '{': // object
11770 return get_ubjson_object();
11771
11772 default: // anything else
11773 break;
11774 }
11775 auto last_token = get_token_string();
11776 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11777 }
11778
11782 bool get_ubjson_array()
11783 {
11784 std::pair<std::size_t, char_int_type> size_and_type;
11785 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11786 {
11787 return false;
11788 }
11789
11790 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11791 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11792
11793 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11794 {
11795 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11796 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
11797 {
11798 return p.first < t;
11799 });
11800 string_t key = "_ArrayType_";
11801 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11802 {
11803 auto last_token = get_token_string();
11804 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11805 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11806 }
11807
11808 string_t type = it->second; // sax->string() takes a reference
11809 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11810 {
11811 return false;
11812 }
11813
11814 if (size_and_type.second == 'C')
11815 {
11816 size_and_type.second = 'U';
11817 }
11818
11819 key = "_ArrayData_";
11820 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11821 {
11822 return false;
11823 }
11824
11825 for (std::size_t i = 0; i < size_and_type.first; ++i)
11826 {
11827 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11828 {
11829 return false;
11830 }
11831 }
11832
11833 return (sax->end_array() && sax->end_object());
11834 }
11835
11836 if (size_and_type.first != npos)
11837 {
11838 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11839 {
11840 return false;
11841 }
11842
11843 if (size_and_type.second != 0)
11844 {
11845 if (size_and_type.second != 'N')
11846 {
11847 for (std::size_t i = 0; i < size_and_type.first; ++i)
11848 {
11849 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11850 {
11851 return false;
11852 }
11853 }
11854 }
11855 }
11856 else
11857 {
11858 for (std::size_t i = 0; i < size_and_type.first; ++i)
11859 {
11860 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11861 {
11862 return false;
11863 }
11864 }
11865 }
11866 }
11867 else
11868 {
11869 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11870 {
11871 return false;
11872 }
11873
11874 while (current != ']')
11875 {
11876 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11877 {
11878 return false;
11879 }
11880 get_ignore_noop();
11881 }
11882 }
11883
11884 return sax->end_array();
11885 }
11886
11890 bool get_ubjson_object()
11891 {
11892 std::pair<std::size_t, char_int_type> size_and_type;
11893 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11894 {
11895 return false;
11896 }
11897
11898 // do not accept ND-array size in objects in BJData
11899 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11900 {
11901 auto last_token = get_token_string();
11902 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11903 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11904 }
11905
11906 string_t key;
11907 if (size_and_type.first != npos)
11908 {
11909 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11910 {
11911 return false;
11912 }
11913
11914 if (size_and_type.second != 0)
11915 {
11916 for (std::size_t i = 0; i < size_and_type.first; ++i)
11917 {
11918 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11919 {
11920 return false;
11921 }
11922 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11923 {
11924 return false;
11925 }
11926 key.clear();
11927 }
11928 }
11929 else
11930 {
11931 for (std::size_t i = 0; i < size_and_type.first; ++i)
11932 {
11933 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11934 {
11935 return false;
11936 }
11937 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11938 {
11939 return false;
11940 }
11941 key.clear();
11942 }
11943 }
11944 }
11945 else
11946 {
11947 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11948 {
11949 return false;
11950 }
11951
11952 while (current != '}')
11953 {
11954 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11955 {
11956 return false;
11957 }
11958 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11959 {
11960 return false;
11961 }
11962 get_ignore_noop();
11963 key.clear();
11964 }
11965 }
11966
11967 return sax->end_object();
11968 }
11969
11970 // Note, no reader for UBJSON binary types is implemented because they do
11971 // not exist
11972
11973 bool get_ubjson_high_precision_number()
11974 {
11975 // get size of following number string
11976 std::size_t size{};
11977 bool no_ndarray = true;
11978 auto res = get_ubjson_size_value(size, no_ndarray);
11979 if (JSON_HEDLEY_UNLIKELY(!res))
11980 {
11981 return res;
11982 }
11983
11984 // get number string
11985 std::vector<char> number_vector;
11986 for (std::size_t i = 0; i < size; ++i)
11987 {
11988 get();
11989 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11990 {
11991 return false;
11992 }
11993 number_vector.push_back(static_cast<char>(current));
11994 }
11995
11996 // parse number string
11997 using ia_type = decltype(detail::input_adapter(number_vector));
11998 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11999 const auto result_number = number_lexer.scan();
12000 const auto number_string = number_lexer.get_token_string();
12001 const auto result_remainder = number_lexer.scan();
12002
12003 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12004
12005 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12006 {
12007 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12008 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12009 }
12010
12011 switch (result_number)
12012 {
12013 case token_type::value_integer:
12014 return sax->number_integer(number_lexer.get_number_integer());
12015 case token_type::value_unsigned:
12016 return sax->number_unsigned(number_lexer.get_number_unsigned());
12017 case token_type::value_float:
12018 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12019 case token_type::uninitialized:
12020 case token_type::literal_true:
12021 case token_type::literal_false:
12022 case token_type::literal_null:
12023 case token_type::value_string:
12024 case token_type::begin_array:
12025 case token_type::begin_object:
12026 case token_type::end_array:
12027 case token_type::end_object:
12028 case token_type::name_separator:
12029 case token_type::value_separator:
12030 case token_type::parse_error:
12031 case token_type::end_of_input:
12032 case token_type::literal_or_value:
12033 default:
12034 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12035 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12036 }
12037 }
12038
12040 // Utility functions //
12042
12052 char_int_type get()
12053 {
12054 ++chars_read;
12055 return current = ia.get_character();
12056 }
12057
12066 template<class T>
12067 bool get_to(T& dest, const input_format_t format, const char* context)
12068 {
12069 auto new_chars_read = ia.get_elements(&dest);
12070 chars_read += new_chars_read;
12071 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12072 {
12073 // in case of failure, advance position by 1 to report failing location
12074 ++chars_read;
12075 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12076 return false;
12077 }
12078 return true;
12079 }
12080
12084 char_int_type get_ignore_noop()
12085 {
12086 do
12087 {
12088 get();
12089 }
12090 while (current == 'N');
12091
12092 return current;
12093 }
12094
12095 template<class NumberType>
12096 static void byte_swap(NumberType& number)
12097 {
12098 constexpr std::size_t sz = sizeof(number);
12099#ifdef __cpp_lib_byteswap
12100 if constexpr (sz == 1)
12101 {
12102 return;
12103 }
12104 if constexpr(std::is_integral_v<NumberType>)
12105 {
12106 number = std::byteswap(number);
12107 return;
12108 }
12109#endif
12110 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12111 for (std::size_t i = 0; i < sz / 2; ++i)
12112 {
12113 std::swap(ptr[i], ptr[sz - i - 1]);
12114 }
12115 }
12116
12117 /*
12118 @brief read a number from the input
12119
12120 @tparam NumberType the type of the number
12121 @param[in] format the current format (for diagnostics)
12122 @param[out] result number of type @a NumberType
12123
12124 @return whether conversion completed
12125
12126 @note This function needs to respect the system's endianness, because
12127 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12128 (big endian) and therefore need reordering on little endian systems.
12129 On the other hand, BSON and BJData use little endian and should reorder
12130 on big endian systems.
12131 */
12132 template<typename NumberType, bool InputIsLittleEndian = false>
12133 bool get_number(const input_format_t format, NumberType& result)
12134 {
12135 // read in the original format
12136
12137 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12138 {
12139 return false;
12140 }
12141 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12142 {
12143 byte_swap(result);
12144 }
12145 return true;
12146 }
12147
12162 template<typename NumberType>
12163 bool get_string(const input_format_t format,
12164 const NumberType len,
12165 string_t& result)
12166 {
12167 bool success = true;
12168 for (NumberType i = 0; i < len; i++)
12169 {
12170 get();
12171 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12172 {
12173 success = false;
12174 break;
12175 }
12176 result.push_back(static_cast<typename string_t::value_type>(current));
12177 }
12178 return success;
12179 }
12180
12195 template<typename NumberType>
12196 bool get_binary(const input_format_t format,
12197 const NumberType len,
12198 binary_t& result)
12199 {
12200 bool success = true;
12201 for (NumberType i = 0; i < len; i++)
12202 {
12203 get();
12204 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12205 {
12206 success = false;
12207 break;
12208 }
12209 result.push_back(static_cast<std::uint8_t>(current));
12210 }
12211 return success;
12212 }
12213
12220 bool unexpect_eof(const input_format_t format, const char* context) const
12221 {
12222 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12223 {
12224 return sax->parse_error(chars_read, "<end of file>",
12225 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12226 }
12227 return true;
12228 }
12229
12233 std::string get_token_string() const
12234 {
12235 std::array<char, 3> cr{{}};
12236 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12237 return std::string{cr.data()};
12238 }
12239
12246 std::string exception_message(const input_format_t format,
12247 const std::string& detail,
12248 const std::string& context) const
12249 {
12250 std::string error_msg = "syntax error while parsing ";
12251
12252 switch (format)
12253 {
12254 case input_format_t::cbor:
12255 error_msg += "CBOR";
12256 break;
12257
12258 case input_format_t::msgpack:
12259 error_msg += "MessagePack";
12260 break;
12261
12262 case input_format_t::ubjson:
12263 error_msg += "UBJSON";
12264 break;
12265
12266 case input_format_t::bson:
12267 error_msg += "BSON";
12268 break;
12269
12270 case input_format_t::bjdata:
12271 error_msg += "BJData";
12272 break;
12273
12274 case input_format_t::json: // LCOV_EXCL_LINE
12275 default: // LCOV_EXCL_LINE
12276 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12277 }
12278
12279 return concat(error_msg, ' ', context, ": ", detail);
12280 }
12281
12282 private:
12283 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12284
12286 InputAdapterType ia;
12287
12289 char_int_type current = char_traits<char_type>::eof();
12290
12292 std::size_t chars_read = 0;
12293
12295 const bool is_little_endian = little_endianness();
12296
12298 const input_format_t input_format = input_format_t::json;
12299
12301 json_sax_t* sax = nullptr;
12302
12303 // excluded markers in bjdata optimized type
12304#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12305 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12306
12307#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12308 make_array<bjd_type>( \
12309 bjd_type{'C', "char"}, \
12310 bjd_type{'D', "double"}, \
12311 bjd_type{'I', "int16"}, \
12312 bjd_type{'L', "int64"}, \
12313 bjd_type{'M', "uint64"}, \
12314 bjd_type{'U', "uint8"}, \
12315 bjd_type{'d', "single"}, \
12316 bjd_type{'i', "int8"}, \
12317 bjd_type{'l', "int32"}, \
12318 bjd_type{'m', "uint32"}, \
12319 bjd_type{'u', "uint16"})
12320
12322 // lookup tables
12323 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12324 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12326
12327 using bjd_type = std::pair<char_int_type, string_t>;
12328 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12329 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12331
12332#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12333#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12334};
12335
12336#ifndef JSON_HAS_CPP_17
12337 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12338 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12339#endif
12340
12341} // namespace detail
12343
12344// #include <nlohmann/detail/input/input_adapters.hpp>
12345
12346// #include <nlohmann/detail/input/lexer.hpp>
12347
12348// #include <nlohmann/detail/input/parser.hpp>
12349// __ _____ _____ _____
12350// __| | __| | | | JSON for Modern C++
12351// | | |__ | | | | | | version 3.11.3
12352// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12353//
12354// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
12355// SPDX-License-Identifier: MIT
12356
12357
12358
12359#include <cmath> // isfinite
12360#include <cstdint> // uint8_t
12361#include <functional> // function
12362#include <string> // string
12363#include <utility> // move
12364#include <vector> // vector
12365
12366// #include <nlohmann/detail/exceptions.hpp>
12367
12368// #include <nlohmann/detail/input/input_adapters.hpp>
12369
12370// #include <nlohmann/detail/input/json_sax.hpp>
12371
12372// #include <nlohmann/detail/input/lexer.hpp>
12373
12374// #include <nlohmann/detail/macro_scope.hpp>
12375
12376// #include <nlohmann/detail/meta/is_sax.hpp>
12377
12378// #include <nlohmann/detail/string_concat.hpp>
12379
12380// #include <nlohmann/detail/value_t.hpp>
12381
12382
12384namespace detail
12385{
12387// parser //
12389
12390enum class parse_event_t : std::uint8_t
12391{
12393 object_start,
12395 object_end,
12397 array_start,
12399 array_end,
12401 key,
12403 value
12404};
12405
12406template<typename BasicJsonType>
12407using parser_callback_t =
12408 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12409
12415template<typename BasicJsonType, typename InputAdapterType>
12416class parser
12417{
12418 using number_integer_t = typename BasicJsonType::number_integer_t;
12419 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12420 using number_float_t = typename BasicJsonType::number_float_t;
12421 using string_t = typename BasicJsonType::string_t;
12422 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12423 using token_type = typename lexer_t::token_type;
12424
12425 public:
12427 explicit parser(InputAdapterType&& adapter,
12428 parser_callback_t<BasicJsonType> cb = nullptr,
12429 const bool allow_exceptions_ = true,
12430 const bool skip_comments = false)
12431 : callback(std::move(cb))
12432 , m_lexer(std::move(adapter), skip_comments)
12433 , allow_exceptions(allow_exceptions_)
12434 {
12435 // read first token
12436 get_token();
12437 }
12438
12449 void parse(const bool strict, BasicJsonType& result)
12450 {
12451 if (callback)
12452 {
12453 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12454 sax_parse_internal(&sdp);
12455
12456 // in strict mode, input must be completely read
12457 if (strict && (get_token() != token_type::end_of_input))
12458 {
12459 sdp.parse_error(m_lexer.get_position(),
12460 m_lexer.get_token_string(),
12461 parse_error::create(101, m_lexer.get_position(),
12462 exception_message(token_type::end_of_input, "value"), nullptr));
12463 }
12464
12465 // in case of an error, return discarded value
12466 if (sdp.is_errored())
12467 {
12468 result = value_t::discarded;
12469 return;
12470 }
12471
12472 // set top-level value to null if it was discarded by the callback
12473 // function
12474 if (result.is_discarded())
12475 {
12476 result = nullptr;
12477 }
12478 }
12479 else
12480 {
12481 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12482 sax_parse_internal(&sdp);
12483
12484 // in strict mode, input must be completely read
12485 if (strict && (get_token() != token_type::end_of_input))
12486 {
12487 sdp.parse_error(m_lexer.get_position(),
12488 m_lexer.get_token_string(),
12489 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12490 }
12491
12492 // in case of an error, return discarded value
12493 if (sdp.is_errored())
12494 {
12495 result = value_t::discarded;
12496 return;
12497 }
12498 }
12499
12500 result.assert_invariant();
12501 }
12502
12509 bool accept(const bool strict = true)
12510 {
12511 json_sax_acceptor<BasicJsonType> sax_acceptor;
12512 return sax_parse(&sax_acceptor, strict);
12513 }
12514
12515 template<typename SAX>
12517 bool sax_parse(SAX* sax, const bool strict = true)
12518 {
12519 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
12520 const bool result = sax_parse_internal(sax);
12521
12522 // strict mode: next byte must be EOF
12523 if (result && strict && (get_token() != token_type::end_of_input))
12524 {
12525 return sax->parse_error(m_lexer.get_position(),
12526 m_lexer.get_token_string(),
12527 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12528 }
12529
12530 return result;
12531 }
12532
12533 private:
12534 template<typename SAX>
12536 bool sax_parse_internal(SAX* sax)
12537 {
12538 // stack to remember the hierarchy of structured values we are parsing
12539 // true = array; false = object
12540 std::vector<bool> states;
12541 // value to avoid a goto (see comment where set to true)
12542 bool skip_to_state_evaluation = false;
12543
12544 while (true)
12545 {
12546 if (!skip_to_state_evaluation)
12547 {
12548 // invariant: get_token() was called before each iteration
12549 switch (last_token)
12550 {
12551 case token_type::begin_object:
12552 {
12553 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12554 {
12555 return false;
12556 }
12557
12558 // closing } -> we are done
12559 if (get_token() == token_type::end_object)
12560 {
12561 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12562 {
12563 return false;
12564 }
12565 break;
12566 }
12567
12568 // parse key
12569 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12570 {
12571 return sax->parse_error(m_lexer.get_position(),
12572 m_lexer.get_token_string(),
12573 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12574 }
12575 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12576 {
12577 return false;
12578 }
12579
12580 // parse separator (:)
12581 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12582 {
12583 return sax->parse_error(m_lexer.get_position(),
12584 m_lexer.get_token_string(),
12585 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12586 }
12587
12588 // remember we are now inside an object
12589 states.push_back(false);
12590
12591 // parse values
12592 get_token();
12593 continue;
12594 }
12595
12596 case token_type::begin_array:
12597 {
12598 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12599 {
12600 return false;
12601 }
12602
12603 // closing ] -> we are done
12604 if (get_token() == token_type::end_array)
12605 {
12606 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12607 {
12608 return false;
12609 }
12610 break;
12611 }
12612
12613 // remember we are now inside an array
12614 states.push_back(true);
12615
12616 // parse values (no need to call get_token)
12617 continue;
12618 }
12619
12620 case token_type::value_float:
12621 {
12622 const auto res = m_lexer.get_number_float();
12623
12624 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12625 {
12626 return sax->parse_error(m_lexer.get_position(),
12627 m_lexer.get_token_string(),
12628 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12629 }
12630
12631 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12632 {
12633 return false;
12634 }
12635
12636 break;
12637 }
12638
12639 case token_type::literal_false:
12640 {
12641 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12642 {
12643 return false;
12644 }
12645 break;
12646 }
12647
12648 case token_type::literal_null:
12649 {
12650 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12651 {
12652 return false;
12653 }
12654 break;
12655 }
12656
12657 case token_type::literal_true:
12658 {
12659 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12660 {
12661 return false;
12662 }
12663 break;
12664 }
12665
12666 case token_type::value_integer:
12667 {
12668 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12669 {
12670 return false;
12671 }
12672 break;
12673 }
12674
12675 case token_type::value_string:
12676 {
12677 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12678 {
12679 return false;
12680 }
12681 break;
12682 }
12683
12684 case token_type::value_unsigned:
12685 {
12686 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12687 {
12688 return false;
12689 }
12690 break;
12691 }
12692
12693 case token_type::parse_error:
12694 {
12695 // using "uninitialized" to avoid "expected" message
12696 return sax->parse_error(m_lexer.get_position(),
12697 m_lexer.get_token_string(),
12698 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12699 }
12700 case token_type::end_of_input:
12701 {
12702 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
12703 {
12704 return sax->parse_error(m_lexer.get_position(),
12705 m_lexer.get_token_string(),
12706 parse_error::create(101, m_lexer.get_position(),
12707 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12708 }
12709
12710 return sax->parse_error(m_lexer.get_position(),
12711 m_lexer.get_token_string(),
12712 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12713 }
12714 case token_type::uninitialized:
12715 case token_type::end_array:
12716 case token_type::end_object:
12717 case token_type::name_separator:
12718 case token_type::value_separator:
12719 case token_type::literal_or_value:
12720 default: // the last token was unexpected
12721 {
12722 return sax->parse_error(m_lexer.get_position(),
12723 m_lexer.get_token_string(),
12724 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12725 }
12726 }
12727 }
12728 else
12729 {
12730 skip_to_state_evaluation = false;
12731 }
12732
12733 // we reached this line after we successfully parsed a value
12734 if (states.empty())
12735 {
12736 // empty stack: we reached the end of the hierarchy: done
12737 return true;
12738 }
12739
12740 if (states.back()) // array
12741 {
12742 // comma -> next value
12743 if (get_token() == token_type::value_separator)
12744 {
12745 // parse a new value
12746 get_token();
12747 continue;
12748 }
12749
12750 // closing ]
12751 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12752 {
12753 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12754 {
12755 return false;
12756 }
12757
12758 // We are done with this array. Before we can parse a
12759 // new value, we need to evaluate the new state first.
12760 // By setting skip_to_state_evaluation to false, we
12761 // are effectively jumping to the beginning of this if.
12762 JSON_ASSERT(!states.empty());
12763 states.pop_back();
12764 skip_to_state_evaluation = true;
12765 continue;
12766 }
12767
12768 return sax->parse_error(m_lexer.get_position(),
12769 m_lexer.get_token_string(),
12770 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12771 }
12772
12773 // states.back() is false -> object
12774
12775 // comma -> next value
12776 if (get_token() == token_type::value_separator)
12777 {
12778 // parse key
12779 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12780 {
12781 return sax->parse_error(m_lexer.get_position(),
12782 m_lexer.get_token_string(),
12783 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12784 }
12785
12786 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12787 {
12788 return false;
12789 }
12790
12791 // parse separator (:)
12792 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12793 {
12794 return sax->parse_error(m_lexer.get_position(),
12795 m_lexer.get_token_string(),
12796 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12797 }
12798
12799 // parse values
12800 get_token();
12801 continue;
12802 }
12803
12804 // closing }
12805 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12806 {
12807 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12808 {
12809 return false;
12810 }
12811
12812 // We are done with this object. Before we can parse a
12813 // new value, we need to evaluate the new state first.
12814 // By setting skip_to_state_evaluation to false, we
12815 // are effectively jumping to the beginning of this if.
12816 JSON_ASSERT(!states.empty());
12817 states.pop_back();
12818 skip_to_state_evaluation = true;
12819 continue;
12820 }
12821
12822 return sax->parse_error(m_lexer.get_position(),
12823 m_lexer.get_token_string(),
12824 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12825 }
12826 }
12827
12829 token_type get_token()
12830 {
12831 return last_token = m_lexer.scan();
12832 }
12833
12834 std::string exception_message(const token_type expected, const std::string& context)
12835 {
12836 std::string error_msg = "syntax error ";
12837
12838 if (!context.empty())
12839 {
12840 error_msg += concat("while parsing ", context, ' ');
12841 }
12842
12843 error_msg += "- ";
12844
12845 if (last_token == token_type::parse_error)
12846 {
12847 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12848 m_lexer.get_token_string(), '\'');
12849 }
12850 else
12851 {
12852 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12853 }
12854
12855 if (expected != token_type::uninitialized)
12856 {
12857 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12858 }
12859
12860 return error_msg;
12861 }
12862
12863 private:
12865 const parser_callback_t<BasicJsonType> callback = nullptr;
12867 token_type last_token = token_type::uninitialized;
12869 lexer_t m_lexer;
12871 const bool allow_exceptions = true;
12872};
12873
12874} // namespace detail
12876
12877// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12878// __ _____ _____ _____
12879// __| | __| | | | JSON for Modern C++
12880// | | |__ | | | | | | version 3.11.3
12881// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12882//
12883// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
12884// SPDX-License-Identifier: MIT
12885
12886
12887
12888// #include <nlohmann/detail/abi_macros.hpp>
12889
12890// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12891// __ _____ _____ _____
12892// __| | __| | | | JSON for Modern C++
12893// | | |__ | | | | | | version 3.11.3
12894// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12895//
12896// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
12897// SPDX-License-Identifier: MIT
12898
12899
12900
12901#include <cstddef> // ptrdiff_t
12902#include <limits> // numeric_limits
12903
12904// #include <nlohmann/detail/macro_scope.hpp>
12905
12906
12908namespace detail
12909{
12910
12911/*
12912@brief an iterator for primitive JSON types
12913
12914This class models an iterator for primitive JSON types (boolean, number,
12915string). It's only purpose is to allow the iterator/const_iterator classes
12916to "iterate" over primitive values. Internally, the iterator is modeled by
12917a `difference_type` variable. Value begin_value (`0`) models the begin,
12918end_value (`1`) models past the end.
12919*/
12920class primitive_iterator_t
12921{
12922 private:
12923 using difference_type = std::ptrdiff_t;
12924 static constexpr difference_type begin_value = 0;
12925 static constexpr difference_type end_value = begin_value + 1;
12926
12929 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12930
12931 public:
12932 constexpr difference_type get_value() const noexcept
12933 {
12934 return m_it;
12935 }
12936
12938 void set_begin() noexcept
12939 {
12940 m_it = begin_value;
12941 }
12942
12944 void set_end() noexcept
12945 {
12946 m_it = end_value;
12947 }
12948
12950 constexpr bool is_begin() const noexcept
12951 {
12952 return m_it == begin_value;
12953 }
12954
12956 constexpr bool is_end() const noexcept
12957 {
12958 return m_it == end_value;
12959 }
12960
12961 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12962 {
12963 return lhs.m_it == rhs.m_it;
12964 }
12965
12966 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12967 {
12968 return lhs.m_it < rhs.m_it;
12969 }
12970
12971 primitive_iterator_t operator+(difference_type n) noexcept
12972 {
12973 auto result = *this;
12974 result += n;
12975 return result;
12976 }
12977
12978 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12979 {
12980 return lhs.m_it - rhs.m_it;
12981 }
12982
12983 primitive_iterator_t& operator++() noexcept
12984 {
12985 ++m_it;
12986 return *this;
12987 }
12988
12989 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12990 {
12991 auto result = *this;
12992 ++m_it;
12993 return result;
12994 }
12995
12996 primitive_iterator_t& operator--() noexcept
12997 {
12998 --m_it;
12999 return *this;
13000 }
13001
13002 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13003 {
13004 auto result = *this;
13005 --m_it;
13006 return result;
13007 }
13008
13009 primitive_iterator_t& operator+=(difference_type n) noexcept
13010 {
13011 m_it += n;
13012 return *this;
13013 }
13014
13015 primitive_iterator_t& operator-=(difference_type n) noexcept
13016 {
13017 m_it -= n;
13018 return *this;
13019 }
13020};
13021
13022} // namespace detail
13024
13025
13027namespace detail
13028{
13029
13036template<typename BasicJsonType> struct internal_iterator
13037{
13039 typename BasicJsonType::object_t::iterator object_iterator {};
13041 typename BasicJsonType::array_t::iterator array_iterator {};
13043 primitive_iterator_t primitive_iterator {};
13044};
13045
13046} // namespace detail
13048
13049// #include <nlohmann/detail/iterators/iter_impl.hpp>
13050// __ _____ _____ _____
13051// __| | __| | | | JSON for Modern C++
13052// | | |__ | | | | | | version 3.11.3
13053// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13054//
13055// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
13056// SPDX-License-Identifier: MIT
13057
13058
13059
13060#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13061#include <type_traits> // conditional, is_const, remove_const
13062
13063// #include <nlohmann/detail/exceptions.hpp>
13064
13065// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13066
13067// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13068
13069// #include <nlohmann/detail/macro_scope.hpp>
13070
13071// #include <nlohmann/detail/meta/cpp_future.hpp>
13072
13073// #include <nlohmann/detail/meta/type_traits.hpp>
13074
13075// #include <nlohmann/detail/value_t.hpp>
13076
13077
13079namespace detail
13080{
13081
13082// forward declare, to be able to friend it later on
13083template<typename IteratorType> class iteration_proxy;
13084template<typename IteratorType> class iteration_proxy_value;
13085
13102template<typename BasicJsonType>
13103class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13104{
13106 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13108 friend other_iter_impl;
13109 friend BasicJsonType;
13112
13113 using object_t = typename BasicJsonType::object_t;
13114 using array_t = typename BasicJsonType::array_t;
13115 // make sure BasicJsonType is basic_json or const basic_json
13117 "iter_impl only accepts (const) basic_json");
13118 // superficial check for the LegacyBidirectionalIterator named requirement
13119 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13120 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13121 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13122
13123 public:
13129 using iterator_category = std::bidirectional_iterator_tag;
13130
13132 using value_type = typename BasicJsonType::value_type;
13134 using difference_type = typename BasicJsonType::difference_type;
13136 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13137 typename BasicJsonType::const_pointer,
13138 typename BasicJsonType::pointer>::type;
13141 typename std::conditional<std::is_const<BasicJsonType>::value,
13142 typename BasicJsonType::const_reference,
13143 typename BasicJsonType::reference>::type;
13144
13145 iter_impl() = default;
13146 ~iter_impl() = default;
13147 iter_impl(iter_impl&&) noexcept = default;
13148 iter_impl& operator=(iter_impl&&) noexcept = default;
13149
13156 explicit iter_impl(pointer object) noexcept : m_object(object)
13157 {
13158 JSON_ASSERT(m_object != nullptr);
13159
13160 switch (m_object->m_data.m_type)
13161 {
13162 case value_t::object:
13163 {
13164 m_it.object_iterator = typename object_t::iterator();
13165 break;
13166 }
13167
13168 case value_t::array:
13169 {
13170 m_it.array_iterator = typename array_t::iterator();
13171 break;
13172 }
13173
13174 case value_t::null:
13175 case value_t::string:
13176 case value_t::boolean:
13180 case value_t::binary:
13181 case value_t::discarded:
13182 default:
13183 {
13184 m_it.primitive_iterator = primitive_iterator_t();
13185 break;
13186 }
13187 }
13188 }
13189
13207 : m_object(other.m_object), m_it(other.m_it)
13208 {}
13209
13217 {
13218 if (&other != this)
13219 {
13220 m_object = other.m_object;
13221 m_it = other.m_it;
13222 }
13223 return *this;
13224 }
13225
13231 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13232 : m_object(other.m_object), m_it(other.m_it)
13233 {}
13234
13241 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13242 {
13243 m_object = other.m_object;
13244 m_it = other.m_it;
13245 return *this;
13246 }
13247
13253 void set_begin() noexcept
13254 {
13255 JSON_ASSERT(m_object != nullptr);
13256
13257 switch (m_object->m_data.m_type)
13258 {
13259 case value_t::object:
13260 {
13261 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13262 break;
13263 }
13264
13265 case value_t::array:
13266 {
13267 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13268 break;
13269 }
13270
13271 case value_t::null:
13272 {
13273 // set to end so begin()==end() is true: null is empty
13274 m_it.primitive_iterator.set_end();
13275 break;
13276 }
13277
13278 case value_t::string:
13279 case value_t::boolean:
13283 case value_t::binary:
13284 case value_t::discarded:
13285 default:
13286 {
13287 m_it.primitive_iterator.set_begin();
13288 break;
13289 }
13290 }
13291 }
13292
13297 void set_end() noexcept
13298 {
13299 JSON_ASSERT(m_object != nullptr);
13300
13301 switch (m_object->m_data.m_type)
13302 {
13303 case value_t::object:
13304 {
13305 m_it.object_iterator = m_object->m_data.m_value.object->end();
13306 break;
13307 }
13308
13309 case value_t::array:
13310 {
13311 m_it.array_iterator = m_object->m_data.m_value.array->end();
13312 break;
13313 }
13314
13315 case value_t::null:
13316 case value_t::string:
13317 case value_t::boolean:
13321 case value_t::binary:
13322 case value_t::discarded:
13323 default:
13324 {
13325 m_it.primitive_iterator.set_end();
13326 break;
13327 }
13328 }
13329 }
13330
13331 public:
13337 {
13338 JSON_ASSERT(m_object != nullptr);
13339
13340 switch (m_object->m_data.m_type)
13341 {
13342 case value_t::object:
13343 {
13344 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13345 return m_it.object_iterator->second;
13346 }
13347
13348 case value_t::array:
13349 {
13350 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13351 return *m_it.array_iterator;
13352 }
13353
13354 case value_t::null:
13355 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13356
13357 case value_t::string:
13358 case value_t::boolean:
13362 case value_t::binary:
13363 case value_t::discarded:
13364 default:
13365 {
13367 {
13368 return *m_object;
13369 }
13370
13371 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13372 }
13373 }
13374 }
13375
13381 {
13382 JSON_ASSERT(m_object != nullptr);
13383
13384 switch (m_object->m_data.m_type)
13385 {
13386 case value_t::object:
13387 {
13388 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13389 return &(m_it.object_iterator->second);
13390 }
13391
13392 case value_t::array:
13393 {
13394 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13395 return &*m_it.array_iterator;
13396 }
13397
13398 case value_t::null:
13399 case value_t::string:
13400 case value_t::boolean:
13404 case value_t::binary:
13405 case value_t::discarded:
13406 default:
13407 {
13409 {
13410 return m_object;
13411 }
13412
13413 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13414 }
13415 }
13416 }
13417
13422 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13423 {
13424 auto result = *this;
13425 ++(*this);
13426 return result;
13427 }
13428
13434 {
13435 JSON_ASSERT(m_object != nullptr);
13436
13437 switch (m_object->m_data.m_type)
13438 {
13439 case value_t::object:
13440 {
13441 std::advance(m_it.object_iterator, 1);
13442 break;
13443 }
13444
13445 case value_t::array:
13446 {
13447 std::advance(m_it.array_iterator, 1);
13448 break;
13449 }
13450
13451 case value_t::null:
13452 case value_t::string:
13453 case value_t::boolean:
13457 case value_t::binary:
13458 case value_t::discarded:
13459 default:
13460 {
13462 break;
13463 }
13464 }
13465
13466 return *this;
13467 }
13468
13473 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13474 {
13475 auto result = *this;
13476 --(*this);
13477 return result;
13478 }
13479
13485 {
13486 JSON_ASSERT(m_object != nullptr);
13487
13488 switch (m_object->m_data.m_type)
13489 {
13490 case value_t::object:
13491 {
13492 std::advance(m_it.object_iterator, -1);
13493 break;
13494 }
13495
13496 case value_t::array:
13497 {
13498 std::advance(m_it.array_iterator, -1);
13499 break;
13500 }
13501
13502 case value_t::null:
13503 case value_t::string:
13504 case value_t::boolean:
13508 case value_t::binary:
13509 case value_t::discarded:
13510 default:
13511 {
13513 break;
13514 }
13515 }
13516
13517 return *this;
13518 }
13519
13524 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13525 bool operator==(const IterImpl& other) const
13526 {
13527 // if objects are not the same, the comparison is undefined
13528 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13529 {
13530 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13531 }
13532
13533 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
13534 if (m_object == nullptr)
13535 {
13536 return true;
13537 }
13538
13539 switch (m_object->m_data.m_type)
13540 {
13541 case value_t::object:
13542 return (m_it.object_iterator == other.m_it.object_iterator);
13543
13544 case value_t::array:
13545 return (m_it.array_iterator == other.m_it.array_iterator);
13546
13547 case value_t::null:
13548 case value_t::string:
13549 case value_t::boolean:
13553 case value_t::binary:
13554 case value_t::discarded:
13555 default:
13556 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13557 }
13558 }
13559
13564 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13565 bool operator!=(const IterImpl& other) const
13566 {
13567 return !operator==(other);
13568 }
13569
13574 bool operator<(const iter_impl& other) const
13575 {
13576 // if objects are not the same, the comparison is undefined
13577 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13578 {
13579 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13580 }
13581
13582 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
13583 if (m_object == nullptr)
13584 {
13585 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
13586 return false;
13587 }
13588
13589 switch (m_object->m_data.m_type)
13590 {
13591 case value_t::object:
13592 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13593
13594 case value_t::array:
13595 return (m_it.array_iterator < other.m_it.array_iterator);
13596
13597 case value_t::null:
13598 case value_t::string:
13599 case value_t::boolean:
13603 case value_t::binary:
13604 case value_t::discarded:
13605 default:
13607 }
13608 }
13609
13614 bool operator<=(const iter_impl& other) const
13615 {
13616 return !other.operator < (*this);
13617 }
13618
13623 bool operator>(const iter_impl& other) const
13624 {
13625 return !operator<=(other);
13626 }
13627
13632 bool operator>=(const iter_impl& other) const
13633 {
13634 return !operator<(other);
13635 }
13636
13642 {
13643 JSON_ASSERT(m_object != nullptr);
13644
13645 switch (m_object->m_data.m_type)
13646 {
13647 case value_t::object:
13648 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13649
13650 case value_t::array:
13651 {
13652 std::advance(m_it.array_iterator, i);
13653 break;
13654 }
13655
13656 case value_t::null:
13657 case value_t::string:
13658 case value_t::boolean:
13662 case value_t::binary:
13663 case value_t::discarded:
13664 default:
13665 {
13667 break;
13668 }
13669 }
13670
13671 return *this;
13672 }
13673
13679 {
13680 return operator+=(-i);
13681 }
13682
13688 {
13689 auto result = *this;
13690 result += i;
13691 return result;
13692 }
13693
13699 {
13700 auto result = it;
13701 result += i;
13702 return result;
13703 }
13704
13710 {
13711 auto result = *this;
13712 result -= i;
13713 return result;
13714 }
13715
13721 {
13722 JSON_ASSERT(m_object != nullptr);
13723
13724 switch (m_object->m_data.m_type)
13725 {
13726 case value_t::object:
13727 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13728
13729 case value_t::array:
13730 return m_it.array_iterator - other.m_it.array_iterator;
13731
13732 case value_t::null:
13733 case value_t::string:
13734 case value_t::boolean:
13738 case value_t::binary:
13739 case value_t::discarded:
13740 default:
13742 }
13743 }
13744
13750 {
13751 JSON_ASSERT(m_object != nullptr);
13752
13753 switch (m_object->m_data.m_type)
13754 {
13755 case value_t::object:
13756 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13757
13758 case value_t::array:
13759 return *std::next(m_it.array_iterator, n);
13760
13761 case value_t::null:
13762 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13763
13764 case value_t::string:
13765 case value_t::boolean:
13769 case value_t::binary:
13770 case value_t::discarded:
13771 default:
13772 {
13773 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13774 {
13775 return *m_object;
13776 }
13777
13778 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13779 }
13780 }
13781 }
13782
13787 const typename object_t::key_type& key() const
13788 {
13789 JSON_ASSERT(m_object != nullptr);
13790
13791 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13792 {
13793 return m_it.object_iterator->first;
13794 }
13795
13796 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13797 }
13798
13804 {
13805 return operator*();
13806 }
13807
13810 pointer m_object = nullptr;
13813};
13814
13815} // namespace detail
13817
13818// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13819
13820// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13821// __ _____ _____ _____
13822// __| | __| | | | JSON for Modern C++
13823// | | |__ | | | | | | version 3.11.3
13824// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13825//
13826// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
13827// SPDX-License-Identifier: MIT
13828
13829
13830
13831#include <cstddef> // ptrdiff_t
13832#include <iterator> // reverse_iterator
13833#include <utility> // declval
13834
13835// #include <nlohmann/detail/abi_macros.hpp>
13836
13837
13839namespace detail
13840{
13841
13843// reverse_iterator //
13845
13864template<typename Base>
13865class json_reverse_iterator : public std::reverse_iterator<Base>
13866{
13867 public:
13868 using difference_type = std::ptrdiff_t;
13870 using base_iterator = std::reverse_iterator<Base>;
13872 using reference = typename Base::reference;
13873
13875 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13876 : base_iterator(it) {}
13877
13879 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13880
13882 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13883 {
13884 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13885 }
13886
13889 {
13890 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13891 }
13892
13894 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13895 {
13896 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13897 }
13898
13901 {
13902 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13903 }
13904
13907 {
13908 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13909 }
13910
13913 {
13914 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13915 }
13916
13919 {
13920 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13921 }
13922
13925 {
13926 return base_iterator(*this) - base_iterator(other);
13927 }
13928
13931 {
13932 return *(this->operator+(n));
13933 }
13934
13936 auto key() const -> decltype(std::declval<Base>().key())
13937 {
13938 auto it = --this->base();
13939 return it.key();
13940 }
13941
13944 {
13945 auto it = --this->base();
13946 return it.operator * ();
13947 }
13948};
13949
13950} // namespace detail
13952
13953// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13954
13955// #include <nlohmann/detail/json_custom_base_class.hpp>
13956// __ _____ _____ _____
13957// __| | __| | | | JSON for Modern C++
13958// | | |__ | | | | | | version 3.11.3
13959// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13960//
13961// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
13962// SPDX-License-Identifier: MIT
13963
13964
13965
13966#include <type_traits> // conditional, is_same
13967
13968// #include <nlohmann/detail/abi_macros.hpp>
13969
13970
13972namespace detail
13973{
13974
13986
13987template<class T>
13988using json_base_class = typename std::conditional <
13989 std::is_same<T, void>::value,
13991 T
13992 >::type;
13993
13994} // namespace detail
13996
13997// #include <nlohmann/detail/json_pointer.hpp>
13998// __ _____ _____ _____
13999// __| | __| | | | JSON for Modern C++
14000// | | |__ | | | | | | version 3.11.3
14001// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14002//
14003// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
14004// SPDX-License-Identifier: MIT
14005
14006
14007
14008#include <algorithm> // all_of
14009#include <cctype> // isdigit
14010#include <cerrno> // errno, ERANGE
14011#include <cstdlib> // strtoull
14012#ifndef JSON_NO_IO
14013 #include <iosfwd> // ostream
14014#endif // JSON_NO_IO
14015#include <limits> // max
14016#include <numeric> // accumulate
14017#include <string> // string
14018#include <utility> // move
14019#include <vector> // vector
14020
14021// #include <nlohmann/detail/exceptions.hpp>
14022
14023// #include <nlohmann/detail/macro_scope.hpp>
14024
14025// #include <nlohmann/detail/string_concat.hpp>
14026
14027// #include <nlohmann/detail/string_escape.hpp>
14028
14029// #include <nlohmann/detail/value_t.hpp>
14030
14031
14033
14036template<typename RefStringType>
14038{
14039 // allow basic_json to access private members
14041 friend class basic_json;
14042
14043 template<typename>
14044 friend class json_pointer;
14045
14046 template<typename T>
14047 struct string_t_helper
14048 {
14049 using type = T;
14050 };
14051
14053 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14054 {
14055 using type = StringType;
14056 };
14057
14058 public:
14059 // for backwards compatibility accept BasicJsonType
14060 using string_t = typename string_t_helper<RefStringType>::type;
14061
14064 explicit json_pointer(const string_t& s = "")
14065 : reference_tokens(split(s))
14066 {}
14067
14071 {
14072 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14073 string_t{},
14074 [](const string_t& a, const string_t& b)
14075 {
14076 return detail::concat(a, '/', detail::escape(b));
14077 });
14078 }
14079
14083 operator string_t() const
14084 {
14085 return to_string();
14086 }
14087
14088#ifndef JSON_NO_IO
14091 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14092 {
14093 o << ptr.to_string();
14094 return o;
14095 }
14096#endif
14097
14101 {
14102 reference_tokens.insert(reference_tokens.end(),
14103 ptr.reference_tokens.begin(),
14104 ptr.reference_tokens.end());
14105 return *this;
14106 }
14107
14111 {
14112 push_back(std::move(token));
14113 return *this;
14114 }
14115
14118 json_pointer& operator/=(std::size_t array_idx)
14119 {
14120 return *this /= std::to_string(array_idx);
14121 }
14122
14126 const json_pointer& rhs)
14127 {
14128 return json_pointer(lhs) /= rhs;
14129 }
14130
14133 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14134 {
14135 return json_pointer(lhs) /= std::move(token);
14136 }
14137
14140 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14141 {
14142 return json_pointer(lhs) /= array_idx;
14143 }
14144
14148 {
14149 if (empty())
14150 {
14151 return *this;
14152 }
14153
14154 json_pointer res = *this;
14155 res.pop_back();
14156 return res;
14157 }
14158
14162 {
14164 {
14165 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14166 }
14167
14168 reference_tokens.pop_back();
14169 }
14170
14173 const string_t& back() const
14174 {
14176 {
14177 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14178 }
14179
14180 return reference_tokens.back();
14181 }
14182
14185 void push_back(const string_t& token)
14186 {
14187 reference_tokens.push_back(token);
14188 }
14189
14192 void push_back(string_t&& token)
14193 {
14194 reference_tokens.push_back(std::move(token));
14195 }
14196
14199 bool empty() const noexcept
14200 {
14201 return reference_tokens.empty();
14202 }
14203
14204 private:
14215 template<typename BasicJsonType>
14216 static typename BasicJsonType::size_type array_index(const string_t& s)
14217 {
14218 using size_type = typename BasicJsonType::size_type;
14219
14220 // error condition (cf. RFC 6901, Sect. 4)
14221 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14222 {
14223 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14224 }
14225
14226 // error condition (cf. RFC 6901, Sect. 4)
14227 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14228 {
14229 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14230 }
14231
14232 const char* p = s.c_str();
14233 char* p_end = nullptr;
14234 errno = 0; // strtoull doesn't reset errno
14235 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14236 if (p == p_end // invalid input or empty string
14237 || errno == ERANGE // out of range
14238 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14239 {
14240 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14241 }
14242
14243 // only triggered on special platforms (like 32bit), see also
14244 // https://github.com/nlohmann/json/pull/2203
14245 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14246 {
14247 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14248 }
14249
14250 return static_cast<size_type>(res);
14251 }
14252
14254 json_pointer top() const
14255 {
14257 {
14258 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14259 }
14260
14261 json_pointer result = *this;
14262 result.reference_tokens = {reference_tokens[0]};
14263 return result;
14264 }
14265
14266 private:
14275 template<typename BasicJsonType>
14276 BasicJsonType& get_and_create(BasicJsonType& j) const
14277 {
14278 auto* result = &j;
14279
14280 // in case no reference tokens exist, return a reference to the JSON value
14281 // j which will be overwritten by a primitive value
14282 for (const auto& reference_token : reference_tokens)
14283 {
14284 switch (result->type())
14285 {
14287 {
14288 if (reference_token == "0")
14289 {
14290 // start a new array if reference token is 0
14291 result = &result->operator[](0);
14292 }
14293 else
14294 {
14295 // start a new object otherwise
14296 result = &result->operator[](reference_token);
14297 }
14298 break;
14299 }
14300
14302 {
14303 // create an entry in the object
14304 result = &result->operator[](reference_token);
14305 break;
14306 }
14307
14309 {
14310 // create an entry in the array
14311 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14312 break;
14313 }
14314
14315 /*
14316 The following code is only reached if there exists a reference
14317 token _and_ the current value is primitive. In this case, we have
14318 an error situation, because primitive values may only occur as
14319 single value; that is, with an empty list of reference tokens.
14320 */
14328 default:
14329 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14330 }
14331 }
14332
14333 return *result;
14334 }
14335
14355 template<typename BasicJsonType>
14356 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14357 {
14358 for (const auto& reference_token : reference_tokens)
14359 {
14360 // convert null values to arrays or objects before continuing
14361 if (ptr->is_null())
14362 {
14363 // check if reference token is a number
14364 const bool nums =
14365 std::all_of(reference_token.begin(), reference_token.end(),
14366 [](const unsigned char x)
14367 {
14368 return std::isdigit(x);
14369 });
14370
14371 // change value to array for numbers or "-" or to object otherwise
14372 *ptr = (nums || reference_token == "-")
14374 : detail::value_t::object;
14375 }
14376
14377 switch (ptr->type())
14378 {
14380 {
14381 // use unchecked object access
14382 ptr = &ptr->operator[](reference_token);
14383 break;
14384 }
14385
14387 {
14388 if (reference_token == "-")
14389 {
14390 // explicitly treat "-" as index beyond the end
14391 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14392 }
14393 else
14394 {
14395 // convert array index to number; unchecked access
14396 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14397 }
14398 break;
14399 }
14400
14409 default:
14410 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14411 }
14412 }
14413
14414 return *ptr;
14415 }
14416
14423 template<typename BasicJsonType>
14424 BasicJsonType& get_checked(BasicJsonType* ptr) const
14425 {
14426 for (const auto& reference_token : reference_tokens)
14427 {
14428 switch (ptr->type())
14429 {
14431 {
14432 // note: at performs range check
14433 ptr = &ptr->at(reference_token);
14434 break;
14435 }
14436
14438 {
14439 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14440 {
14441 // "-" always fails the range check
14443 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14444 ") is out of range"), ptr));
14445 }
14446
14447 // note: at performs range check
14448 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14449 break;
14450 }
14451
14460 default:
14461 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14462 }
14463 }
14464
14465 return *ptr;
14466 }
14467
14481 template<typename BasicJsonType>
14482 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14483 {
14484 for (const auto& reference_token : reference_tokens)
14485 {
14486 switch (ptr->type())
14487 {
14489 {
14490 // use unchecked object access
14491 ptr = &ptr->operator[](reference_token);
14492 break;
14493 }
14494
14496 {
14497 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14498 {
14499 // "-" cannot be used for const access
14500 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
14501 }
14502
14503 // use unchecked array access
14504 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14505 break;
14506 }
14507
14516 default:
14517 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14518 }
14519 }
14520
14521 return *ptr;
14522 }
14523
14530 template<typename BasicJsonType>
14531 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14532 {
14533 for (const auto& reference_token : reference_tokens)
14534 {
14535 switch (ptr->type())
14536 {
14538 {
14539 // note: at performs range check
14540 ptr = &ptr->at(reference_token);
14541 break;
14542 }
14543
14545 {
14546 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14547 {
14548 // "-" always fails the range check
14550 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14551 ") is out of range"), ptr));
14552 }
14553
14554 // note: at performs range check
14555 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14556 break;
14557 }
14558
14567 default:
14568 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14569 }
14570 }
14571
14572 return *ptr;
14573 }
14574
14579 template<typename BasicJsonType>
14580 bool contains(const BasicJsonType* ptr) const
14581 {
14582 for (const auto& reference_token : reference_tokens)
14583 {
14584 switch (ptr->type())
14585 {
14587 {
14588 if (!ptr->contains(reference_token))
14589 {
14590 // we did not find the key in the object
14591 return false;
14592 }
14593
14594 ptr = &ptr->operator[](reference_token);
14595 break;
14596 }
14597
14599 {
14600 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14601 {
14602 // "-" always fails the range check
14603 return false;
14604 }
14605 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14606 {
14607 // invalid char
14608 return false;
14609 }
14610 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14611 {
14612 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14613 {
14614 // first char should be between '1' and '9'
14615 return false;
14616 }
14617 for (std::size_t i = 1; i < reference_token.size(); i++)
14618 {
14619 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14620 {
14621 // other char should be between '0' and '9'
14622 return false;
14623 }
14624 }
14625 }
14626
14627 const auto idx = array_index<BasicJsonType>(reference_token);
14628 if (idx >= ptr->size())
14629 {
14630 // index out of range
14631 return false;
14632 }
14633
14634 ptr = &ptr->operator[](idx);
14635 break;
14636 }
14637
14646 default:
14647 {
14648 // we do not expect primitive values if there is still a
14649 // reference token to process
14650 return false;
14651 }
14652 }
14653 }
14654
14655 // no reference token left means we found a primitive value
14656 return true;
14657 }
14658
14668 static std::vector<string_t> split(const string_t& reference_string)
14669 {
14670 std::vector<string_t> result;
14671
14672 // special case: empty reference string -> no reference tokens
14673 if (reference_string.empty())
14674 {
14675 return result;
14676 }
14677
14678 // check if nonempty reference string begins with slash
14679 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14680 {
14681 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14682 }
14683
14684 // extract the reference tokens:
14685 // - slash: position of the last read slash (or end of string)
14686 // - start: position after the previous slash
14687 for (
14688 // search for the first slash after the first character
14689 std::size_t slash = reference_string.find_first_of('/', 1),
14690 // set the beginning of the first reference token
14691 start = 1;
14692 // we can stop if start == 0 (if slash == string_t::npos)
14693 start != 0;
14694 // set the beginning of the next reference token
14695 // (will eventually be 0 if slash == string_t::npos)
14696 start = (slash == string_t::npos) ? 0 : slash + 1,
14697 // find next slash
14698 slash = reference_string.find_first_of('/', start))
14699 {
14700 // use the text between the beginning of the reference token
14701 // (start) and the last slash (slash).
14702 auto reference_token = reference_string.substr(start, slash - start);
14703
14704 // check reference tokens are properly escaped
14705 for (std::size_t pos = reference_token.find_first_of('~');
14706 pos != string_t::npos;
14707 pos = reference_token.find_first_of('~', pos + 1))
14708 {
14709 JSON_ASSERT(reference_token[pos] == '~');
14710
14711 // ~ must be followed by 0 or 1
14712 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14713 (reference_token[pos + 1] != '0' &&
14714 reference_token[pos + 1] != '1')))
14715 {
14716 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14717 }
14718 }
14719
14720 // finally, store the reference token
14721 detail::unescape(reference_token);
14722 result.push_back(reference_token);
14723 }
14724
14725 return result;
14726 }
14727
14728 private:
14736 template<typename BasicJsonType>
14737 static void flatten(const string_t& reference_string,
14738 const BasicJsonType& value,
14739 BasicJsonType& result)
14740 {
14741 switch (value.type())
14742 {
14744 {
14745 if (value.m_data.m_value.array->empty())
14746 {
14747 // flatten empty array as null
14748 result[reference_string] = nullptr;
14749 }
14750 else
14751 {
14752 // iterate array and use index as reference string
14753 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14754 {
14755 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14756 value.m_data.m_value.array->operator[](i), result);
14757 }
14758 }
14759 break;
14760 }
14761
14763 {
14764 if (value.m_data.m_value.object->empty())
14765 {
14766 // flatten empty object as null
14767 result[reference_string] = nullptr;
14768 }
14769 else
14770 {
14771 // iterate object and use keys as reference string
14772 for (const auto& element : *value.m_data.m_value.object)
14773 {
14774 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14775 }
14776 }
14777 break;
14778 }
14779
14788 default:
14789 {
14790 // add primitive value with its reference string
14791 result[reference_string] = value;
14792 break;
14793 }
14794 }
14795 }
14796
14807 template<typename BasicJsonType>
14808 static BasicJsonType
14809 unflatten(const BasicJsonType& value)
14810 {
14811 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14812 {
14813 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14814 }
14815
14816 BasicJsonType result;
14817
14818 // iterate the JSON object values
14819 for (const auto& element : *value.m_data.m_value.object)
14820 {
14821 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14822 {
14823 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14824 }
14825
14826 // assign value to reference pointed to by JSON pointer; Note that if
14827 // the JSON pointer is "" (i.e., points to the whole value), function
14828 // get_and_create returns a reference to result itself. An assignment
14829 // will then create a primitive value.
14830 json_pointer(element.first).get_and_create(result) = element.second;
14831 }
14832
14833 return result;
14834 }
14835
14836 // can't use conversion operator because of ambiguity
14837 json_pointer<string_t> convert() const&
14838 {
14840 result.reference_tokens = reference_tokens;
14841 return result;
14842 }
14843
14844 json_pointer<string_t> convert()&&
14845 {
14847 result.reference_tokens = std::move(reference_tokens);
14848 return result;
14849 }
14850
14851 public:
14852#if JSON_HAS_THREE_WAY_COMPARISON
14855 template<typename RefStringTypeRhs>
14856 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14857 {
14858 return reference_tokens == rhs.reference_tokens;
14859 }
14860
14863 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14864 bool operator==(const string_t& rhs) const
14865 {
14866 return *this == json_pointer(rhs);
14867 }
14868
14870 template<typename RefStringTypeRhs>
14871 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14872 {
14873 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14874 }
14875#else
14878 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14879 // NOLINTNEXTLINE(readability-redundant-declaration)
14880 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14881 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14882
14885 template<typename RefStringTypeLhs, typename StringType>
14886 // NOLINTNEXTLINE(readability-redundant-declaration)
14887 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14888 const StringType& rhs);
14889
14892 template<typename RefStringTypeRhs, typename StringType>
14893 // NOLINTNEXTLINE(readability-redundant-declaration)
14894 friend bool operator==(const StringType& lhs,
14896
14899 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14900 // NOLINTNEXTLINE(readability-redundant-declaration)
14901 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14902 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14903
14906 template<typename RefStringTypeLhs, typename StringType>
14907 // NOLINTNEXTLINE(readability-redundant-declaration)
14908 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14909 const StringType& rhs);
14910
14913 template<typename RefStringTypeRhs, typename StringType>
14914 // NOLINTNEXTLINE(readability-redundant-declaration)
14915 friend bool operator!=(const StringType& lhs,
14917
14919 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14920 // NOLINTNEXTLINE(readability-redundant-declaration)
14921 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14922 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14923#endif
14924
14925 private:
14927 std::vector<string_t> reference_tokens;
14928};
14929
14930#if !JSON_HAS_THREE_WAY_COMPARISON
14931// functions cannot be defined inside class due to ODR violations
14932template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14933inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14934 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14935{
14936 return lhs.reference_tokens == rhs.reference_tokens;
14937}
14938
14939template<typename RefStringTypeLhs,
14940 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14942inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14943 const StringType& rhs)
14944{
14945 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14946}
14947
14948template<typename RefStringTypeRhs,
14949 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14951inline bool operator==(const StringType& lhs,
14952 const json_pointer<RefStringTypeRhs>& rhs)
14953{
14954 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14955}
14956
14957template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14958inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14959 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14960{
14961 return !(lhs == rhs);
14962}
14963
14964template<typename RefStringTypeLhs,
14965 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14967inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14968 const StringType& rhs)
14969{
14970 return !(lhs == rhs);
14971}
14972
14973template<typename RefStringTypeRhs,
14974 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14976inline bool operator!=(const StringType& lhs,
14977 const json_pointer<RefStringTypeRhs>& rhs)
14978{
14979 return !(lhs == rhs);
14980}
14981
14982template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14984 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14985{
14986 return lhs.reference_tokens < rhs.reference_tokens;
14987}
14988#endif
14989
14991
14992// #include <nlohmann/detail/json_ref.hpp>
14993// __ _____ _____ _____
14994// __| | __| | | | JSON for Modern C++
14995// | | |__ | | | | | | version 3.11.3
14996// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14997//
14998// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
14999// SPDX-License-Identifier: MIT
15000
15001
15002
15003#include <initializer_list>
15004#include <utility>
15005
15006// #include <nlohmann/detail/abi_macros.hpp>
15007
15008// #include <nlohmann/detail/meta/type_traits.hpp>
15009
15010
15012namespace detail
15013{
15014
15015template<typename BasicJsonType>
15017{
15018 public:
15019 using value_type = BasicJsonType;
15020
15022 : owned_value(std::move(value))
15023 {}
15024
15026 : value_ref(&value)
15027 {}
15028
15029 json_ref(std::initializer_list<json_ref> init)
15030 : owned_value(init)
15031 {}
15032
15033 template <
15034 class... Args,
15035 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15036 json_ref(Args && ... args)
15037 : owned_value(std::forward<Args>(args)...)
15038 {}
15039
15040 // class should be movable only
15041 json_ref(json_ref&&) noexcept = default;
15042 json_ref(const json_ref&) = delete;
15043 json_ref& operator=(const json_ref&) = delete;
15044 json_ref& operator=(json_ref&&) = delete;
15045 ~json_ref() = default;
15046
15048 {
15049 if (value_ref == nullptr)
15050 {
15051 return std::move(owned_value);
15052 }
15053 return *value_ref;
15054 }
15055
15056 value_type const& operator*() const
15057 {
15058 return value_ref ? *value_ref : owned_value;
15059 }
15060
15061 value_type const* operator->() const
15062 {
15063 return &** this;
15064 }
15065
15066 private:
15067 mutable value_type owned_value = nullptr;
15068 value_type const* value_ref = nullptr;
15069};
15070
15071} // namespace detail
15073
15074// #include <nlohmann/detail/macro_scope.hpp>
15075
15076// #include <nlohmann/detail/string_concat.hpp>
15077
15078// #include <nlohmann/detail/string_escape.hpp>
15079
15080// #include <nlohmann/detail/meta/cpp_future.hpp>
15081
15082// #include <nlohmann/detail/meta/type_traits.hpp>
15083
15084// #include <nlohmann/detail/output/binary_writer.hpp>
15085// __ _____ _____ _____
15086// __| | __| | | | JSON for Modern C++
15087// | | |__ | | | | | | version 3.11.3
15088// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15089//
15090// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
15091// SPDX-License-Identifier: MIT
15092
15093
15094
15095#include <algorithm> // reverse
15096#include <array> // array
15097#include <map> // map
15098#include <cmath> // isnan, isinf
15099#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15100#include <cstring> // memcpy
15101#include <limits> // numeric_limits
15102#include <string> // string
15103#include <utility> // move
15104#include <vector> // vector
15105
15106// #include <nlohmann/detail/input/binary_reader.hpp>
15107
15108// #include <nlohmann/detail/macro_scope.hpp>
15109
15110// #include <nlohmann/detail/output/output_adapters.hpp>
15111// __ _____ _____ _____
15112// __| | __| | | | JSON for Modern C++
15113// | | |__ | | | | | | version 3.11.3
15114// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15115//
15116// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
15117// SPDX-License-Identifier: MIT
15118
15119
15120
15121#include <algorithm> // copy
15122#include <cstddef> // size_t
15123#include <iterator> // back_inserter
15124#include <memory> // shared_ptr, make_shared
15125#include <string> // basic_string
15126#include <vector> // vector
15127
15128#ifndef JSON_NO_IO
15129 #include <ios> // streamsize
15130 #include <ostream> // basic_ostream
15131#endif // JSON_NO_IO
15132
15133// #include <nlohmann/detail/macro_scope.hpp>
15134
15135
15137namespace detail
15138{
15139
15141template<typename CharType> struct output_adapter_protocol
15142{
15143 virtual void write_character(CharType c) = 0;
15144 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15145 virtual ~output_adapter_protocol() = default;
15146
15147 output_adapter_protocol() = default;
15148 output_adapter_protocol(const output_adapter_protocol&) = default;
15149 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
15150 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
15151 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15152};
15153
15155template<typename CharType>
15156using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15157
15159template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15160class output_vector_adapter : public output_adapter_protocol<CharType>
15161{
15162 public:
15163 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15164 : v(vec)
15165 {}
15166
15167 void write_character(CharType c) override
15168 {
15169 v.push_back(c);
15170 }
15171
15173 void write_characters(const CharType* s, std::size_t length) override
15174 {
15175 v.insert(v.end(), s, s + length);
15176 }
15177
15178 private:
15179 std::vector<CharType, AllocatorType>& v;
15180};
15181
15182#ifndef JSON_NO_IO
15184template<typename CharType>
15185class output_stream_adapter : public output_adapter_protocol<CharType>
15186{
15187 public:
15188 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15189 : stream(s)
15190 {}
15191
15192 void write_character(CharType c) override
15193 {
15194 stream.put(c);
15195 }
15196
15198 void write_characters(const CharType* s, std::size_t length) override
15199 {
15200 stream.write(s, static_cast<std::streamsize>(length));
15201 }
15202
15203 private:
15204 std::basic_ostream<CharType>& stream;
15205};
15206#endif // JSON_NO_IO
15207
15209template<typename CharType, typename StringType = std::basic_string<CharType>>
15210class output_string_adapter : public output_adapter_protocol<CharType>
15211{
15212 public:
15213 explicit output_string_adapter(StringType& s) noexcept
15214 : str(s)
15215 {}
15216
15217 void write_character(CharType c) override
15218 {
15219 str.push_back(c);
15220 }
15221
15223 void write_characters(const CharType* s, std::size_t length) override
15224 {
15225 str.append(s, length);
15226 }
15227
15228 private:
15229 StringType& str;
15230};
15231
15232template<typename CharType, typename StringType = std::basic_string<CharType>>
15233class output_adapter
15234{
15235 public:
15236 template<typename AllocatorType = std::allocator<CharType>>
15237 output_adapter(std::vector<CharType, AllocatorType>& vec)
15238 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15239
15240#ifndef JSON_NO_IO
15241 output_adapter(std::basic_ostream<CharType>& s)
15242 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15243#endif // JSON_NO_IO
15244
15245 output_adapter(StringType& s)
15246 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15247
15248 operator output_adapter_t<CharType>()
15249 {
15250 return oa;
15251 }
15252
15253 private:
15254 output_adapter_t<CharType> oa = nullptr;
15255};
15256
15257} // namespace detail
15259
15260// #include <nlohmann/detail/string_concat.hpp>
15261
15262
15264namespace detail
15265{
15266
15268// binary writer //
15270
15274template<typename BasicJsonType, typename CharType>
15275class binary_writer
15276{
15277 using string_t = typename BasicJsonType::string_t;
15278 using binary_t = typename BasicJsonType::binary_t;
15279 using number_float_t = typename BasicJsonType::number_float_t;
15280
15281 public:
15287 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15288 {
15289 JSON_ASSERT(oa);
15290 }
15291
15296 void write_bson(const BasicJsonType& j)
15297 {
15298 switch (j.type())
15299 {
15300 case value_t::object:
15301 {
15302 write_bson_object(*j.m_data.m_value.object);
15303 break;
15304 }
15305
15306 case value_t::null:
15307 case value_t::array:
15308 case value_t::string:
15309 case value_t::boolean:
15310 case value_t::number_integer:
15311 case value_t::number_unsigned:
15312 case value_t::number_float:
15313 case value_t::binary:
15314 case value_t::discarded:
15315 default:
15316 {
15317 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15318 }
15319 }
15320 }
15321
15325 void write_cbor(const BasicJsonType& j)
15326 {
15327 switch (j.type())
15328 {
15329 case value_t::null:
15330 {
15331 oa->write_character(to_char_type(0xF6));
15332 break;
15333 }
15334
15335 case value_t::boolean:
15336 {
15337 oa->write_character(j.m_data.m_value.boolean
15338 ? to_char_type(0xF5)
15339 : to_char_type(0xF4));
15340 break;
15341 }
15342
15343 case value_t::number_integer:
15344 {
15345 if (j.m_data.m_value.number_integer >= 0)
15346 {
15347 // CBOR does not differentiate between positive signed
15348 // integers and unsigned integers. Therefore, we used the
15349 // code from the value_t::number_unsigned case here.
15350 if (j.m_data.m_value.number_integer <= 0x17)
15351 {
15352 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15353 }
15354 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15355 {
15356 oa->write_character(to_char_type(0x18));
15357 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15358 }
15359 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15360 {
15361 oa->write_character(to_char_type(0x19));
15362 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15363 }
15364 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15365 {
15366 oa->write_character(to_char_type(0x1A));
15367 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15368 }
15369 else
15370 {
15371 oa->write_character(to_char_type(0x1B));
15372 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15373 }
15374 }
15375 else
15376 {
15377 // The conversions below encode the sign in the first
15378 // byte, and the value is converted to a positive number.
15379 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15380 if (j.m_data.m_value.number_integer >= -24)
15381 {
15382 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15383 }
15384 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15385 {
15386 oa->write_character(to_char_type(0x38));
15387 write_number(static_cast<std::uint8_t>(positive_number));
15388 }
15389 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15390 {
15391 oa->write_character(to_char_type(0x39));
15392 write_number(static_cast<std::uint16_t>(positive_number));
15393 }
15394 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15395 {
15396 oa->write_character(to_char_type(0x3A));
15397 write_number(static_cast<std::uint32_t>(positive_number));
15398 }
15399 else
15400 {
15401 oa->write_character(to_char_type(0x3B));
15402 write_number(static_cast<std::uint64_t>(positive_number));
15403 }
15404 }
15405 break;
15406 }
15407
15408 case value_t::number_unsigned:
15409 {
15410 if (j.m_data.m_value.number_unsigned <= 0x17)
15411 {
15412 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15413 }
15414 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15415 {
15416 oa->write_character(to_char_type(0x18));
15417 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15418 }
15419 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15420 {
15421 oa->write_character(to_char_type(0x19));
15422 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15423 }
15424 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15425 {
15426 oa->write_character(to_char_type(0x1A));
15427 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15428 }
15429 else
15430 {
15431 oa->write_character(to_char_type(0x1B));
15432 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15433 }
15434 break;
15435 }
15436
15437 case value_t::number_float:
15438 {
15439 if (std::isnan(j.m_data.m_value.number_float))
15440 {
15441 // NaN is 0xf97e00 in CBOR
15442 oa->write_character(to_char_type(0xF9));
15443 oa->write_character(to_char_type(0x7E));
15444 oa->write_character(to_char_type(0x00));
15445 }
15446 else if (std::isinf(j.m_data.m_value.number_float))
15447 {
15448 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15449 oa->write_character(to_char_type(0xf9));
15450 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15451 oa->write_character(to_char_type(0x00));
15452 }
15453 else
15454 {
15455 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15456 }
15457 break;
15458 }
15459
15460 case value_t::string:
15461 {
15462 // step 1: write control byte and the string length
15463 const auto N = j.m_data.m_value.string->size();
15464 if (N <= 0x17)
15465 {
15466 write_number(static_cast<std::uint8_t>(0x60 + N));
15467 }
15468 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15469 {
15470 oa->write_character(to_char_type(0x78));
15471 write_number(static_cast<std::uint8_t>(N));
15472 }
15473 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15474 {
15475 oa->write_character(to_char_type(0x79));
15476 write_number(static_cast<std::uint16_t>(N));
15477 }
15478 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15479 {
15480 oa->write_character(to_char_type(0x7A));
15481 write_number(static_cast<std::uint32_t>(N));
15482 }
15483 // LCOV_EXCL_START
15484 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15485 {
15486 oa->write_character(to_char_type(0x7B));
15487 write_number(static_cast<std::uint64_t>(N));
15488 }
15489 // LCOV_EXCL_STOP
15490
15491 // step 2: write the string
15492 oa->write_characters(
15493 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15494 j.m_data.m_value.string->size());
15495 break;
15496 }
15497
15498 case value_t::array:
15499 {
15500 // step 1: write control byte and the array size
15501 const auto N = j.m_data.m_value.array->size();
15502 if (N <= 0x17)
15503 {
15504 write_number(static_cast<std::uint8_t>(0x80 + N));
15505 }
15506 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15507 {
15508 oa->write_character(to_char_type(0x98));
15509 write_number(static_cast<std::uint8_t>(N));
15510 }
15511 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15512 {
15513 oa->write_character(to_char_type(0x99));
15514 write_number(static_cast<std::uint16_t>(N));
15515 }
15516 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15517 {
15518 oa->write_character(to_char_type(0x9A));
15519 write_number(static_cast<std::uint32_t>(N));
15520 }
15521 // LCOV_EXCL_START
15522 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15523 {
15524 oa->write_character(to_char_type(0x9B));
15525 write_number(static_cast<std::uint64_t>(N));
15526 }
15527 // LCOV_EXCL_STOP
15528
15529 // step 2: write each element
15530 for (const auto& el : *j.m_data.m_value.array)
15531 {
15532 write_cbor(el);
15533 }
15534 break;
15535 }
15536
15537 case value_t::binary:
15538 {
15539 if (j.m_data.m_value.binary->has_subtype())
15540 {
15541 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15542 {
15543 write_number(static_cast<std::uint8_t>(0xd8));
15544 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15545 }
15546 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15547 {
15548 write_number(static_cast<std::uint8_t>(0xd9));
15549 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15550 }
15551 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15552 {
15553 write_number(static_cast<std::uint8_t>(0xda));
15554 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15555 }
15556 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15557 {
15558 write_number(static_cast<std::uint8_t>(0xdb));
15559 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15560 }
15561 }
15562
15563 // step 1: write control byte and the binary array size
15564 const auto N = j.m_data.m_value.binary->size();
15565 if (N <= 0x17)
15566 {
15567 write_number(static_cast<std::uint8_t>(0x40 + N));
15568 }
15569 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15570 {
15571 oa->write_character(to_char_type(0x58));
15572 write_number(static_cast<std::uint8_t>(N));
15573 }
15574 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15575 {
15576 oa->write_character(to_char_type(0x59));
15577 write_number(static_cast<std::uint16_t>(N));
15578 }
15579 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15580 {
15581 oa->write_character(to_char_type(0x5A));
15582 write_number(static_cast<std::uint32_t>(N));
15583 }
15584 // LCOV_EXCL_START
15585 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15586 {
15587 oa->write_character(to_char_type(0x5B));
15588 write_number(static_cast<std::uint64_t>(N));
15589 }
15590 // LCOV_EXCL_STOP
15591
15592 // step 2: write each element
15593 oa->write_characters(
15594 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15595 N);
15596
15597 break;
15598 }
15599
15600 case value_t::object:
15601 {
15602 // step 1: write control byte and the object size
15603 const auto N = j.m_data.m_value.object->size();
15604 if (N <= 0x17)
15605 {
15606 write_number(static_cast<std::uint8_t>(0xA0 + N));
15607 }
15608 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15609 {
15610 oa->write_character(to_char_type(0xB8));
15611 write_number(static_cast<std::uint8_t>(N));
15612 }
15613 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15614 {
15615 oa->write_character(to_char_type(0xB9));
15616 write_number(static_cast<std::uint16_t>(N));
15617 }
15618 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15619 {
15620 oa->write_character(to_char_type(0xBA));
15621 write_number(static_cast<std::uint32_t>(N));
15622 }
15623 // LCOV_EXCL_START
15624 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15625 {
15626 oa->write_character(to_char_type(0xBB));
15627 write_number(static_cast<std::uint64_t>(N));
15628 }
15629 // LCOV_EXCL_STOP
15630
15631 // step 2: write each element
15632 for (const auto& el : *j.m_data.m_value.object)
15633 {
15634 write_cbor(el.first);
15635 write_cbor(el.second);
15636 }
15637 break;
15638 }
15639
15640 case value_t::discarded:
15641 default:
15642 break;
15643 }
15644 }
15645
15649 void write_msgpack(const BasicJsonType& j)
15650 {
15651 switch (j.type())
15652 {
15653 case value_t::null: // nil
15654 {
15655 oa->write_character(to_char_type(0xC0));
15656 break;
15657 }
15658
15659 case value_t::boolean: // true and false
15660 {
15661 oa->write_character(j.m_data.m_value.boolean
15662 ? to_char_type(0xC3)
15663 : to_char_type(0xC2));
15664 break;
15665 }
15666
15667 case value_t::number_integer:
15668 {
15669 if (j.m_data.m_value.number_integer >= 0)
15670 {
15671 // MessagePack does not differentiate between positive
15672 // signed integers and unsigned integers. Therefore, we used
15673 // the code from the value_t::number_unsigned case here.
15674 if (j.m_data.m_value.number_unsigned < 128)
15675 {
15676 // positive fixnum
15677 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15678 }
15679 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15680 {
15681 // uint 8
15682 oa->write_character(to_char_type(0xCC));
15683 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15684 }
15685 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15686 {
15687 // uint 16
15688 oa->write_character(to_char_type(0xCD));
15689 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15690 }
15691 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15692 {
15693 // uint 32
15694 oa->write_character(to_char_type(0xCE));
15695 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15696 }
15697 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15698 {
15699 // uint 64
15700 oa->write_character(to_char_type(0xCF));
15701 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15702 }
15703 }
15704 else
15705 {
15706 if (j.m_data.m_value.number_integer >= -32)
15707 {
15708 // negative fixnum
15709 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15710 }
15711 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15712 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15713 {
15714 // int 8
15715 oa->write_character(to_char_type(0xD0));
15716 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15717 }
15718 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15719 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15720 {
15721 // int 16
15722 oa->write_character(to_char_type(0xD1));
15723 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15724 }
15725 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15726 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15727 {
15728 // int 32
15729 oa->write_character(to_char_type(0xD2));
15730 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15731 }
15732 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15733 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15734 {
15735 // int 64
15736 oa->write_character(to_char_type(0xD3));
15737 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15738 }
15739 }
15740 break;
15741 }
15742
15743 case value_t::number_unsigned:
15744 {
15745 if (j.m_data.m_value.number_unsigned < 128)
15746 {
15747 // positive fixnum
15748 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15749 }
15750 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15751 {
15752 // uint 8
15753 oa->write_character(to_char_type(0xCC));
15754 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15755 }
15756 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15757 {
15758 // uint 16
15759 oa->write_character(to_char_type(0xCD));
15760 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15761 }
15762 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15763 {
15764 // uint 32
15765 oa->write_character(to_char_type(0xCE));
15766 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15767 }
15768 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15769 {
15770 // uint 64
15771 oa->write_character(to_char_type(0xCF));
15772 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15773 }
15774 break;
15775 }
15776
15777 case value_t::number_float:
15778 {
15779 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15780 break;
15781 }
15782
15783 case value_t::string:
15784 {
15785 // step 1: write control byte and the string length
15786 const auto N = j.m_data.m_value.string->size();
15787 if (N <= 31)
15788 {
15789 // fixstr
15790 write_number(static_cast<std::uint8_t>(0xA0 | N));
15791 }
15792 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15793 {
15794 // str 8
15795 oa->write_character(to_char_type(0xD9));
15796 write_number(static_cast<std::uint8_t>(N));
15797 }
15798 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15799 {
15800 // str 16
15801 oa->write_character(to_char_type(0xDA));
15802 write_number(static_cast<std::uint16_t>(N));
15803 }
15804 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15805 {
15806 // str 32
15807 oa->write_character(to_char_type(0xDB));
15808 write_number(static_cast<std::uint32_t>(N));
15809 }
15810
15811 // step 2: write the string
15812 oa->write_characters(
15813 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15814 j.m_data.m_value.string->size());
15815 break;
15816 }
15817
15818 case value_t::array:
15819 {
15820 // step 1: write control byte and the array size
15821 const auto N = j.m_data.m_value.array->size();
15822 if (N <= 15)
15823 {
15824 // fixarray
15825 write_number(static_cast<std::uint8_t>(0x90 | N));
15826 }
15827 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15828 {
15829 // array 16
15830 oa->write_character(to_char_type(0xDC));
15831 write_number(static_cast<std::uint16_t>(N));
15832 }
15833 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15834 {
15835 // array 32
15836 oa->write_character(to_char_type(0xDD));
15837 write_number(static_cast<std::uint32_t>(N));
15838 }
15839
15840 // step 2: write each element
15841 for (const auto& el : *j.m_data.m_value.array)
15842 {
15843 write_msgpack(el);
15844 }
15845 break;
15846 }
15847
15848 case value_t::binary:
15849 {
15850 // step 0: determine if the binary type has a set subtype to
15851 // determine whether to use the ext or fixext types
15852 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15853
15854 // step 1: write control byte and the byte string length
15855 const auto N = j.m_data.m_value.binary->size();
15856 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15857 {
15858 std::uint8_t output_type{};
15859 bool fixed = true;
15860 if (use_ext)
15861 {
15862 switch (N)
15863 {
15864 case 1:
15865 output_type = 0xD4; // fixext 1
15866 break;
15867 case 2:
15868 output_type = 0xD5; // fixext 2
15869 break;
15870 case 4:
15871 output_type = 0xD6; // fixext 4
15872 break;
15873 case 8:
15874 output_type = 0xD7; // fixext 8
15875 break;
15876 case 16:
15877 output_type = 0xD8; // fixext 16
15878 break;
15879 default:
15880 output_type = 0xC7; // ext 8
15881 fixed = false;
15882 break;
15883 }
15884
15885 }
15886 else
15887 {
15888 output_type = 0xC4; // bin 8
15889 fixed = false;
15890 }
15891
15892 oa->write_character(to_char_type(output_type));
15893 if (!fixed)
15894 {
15895 write_number(static_cast<std::uint8_t>(N));
15896 }
15897 }
15898 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15899 {
15900 const std::uint8_t output_type = use_ext
15901 ? 0xC8 // ext 16
15902 : 0xC5; // bin 16
15903
15904 oa->write_character(to_char_type(output_type));
15905 write_number(static_cast<std::uint16_t>(N));
15906 }
15907 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15908 {
15909 const std::uint8_t output_type = use_ext
15910 ? 0xC9 // ext 32
15911 : 0xC6; // bin 32
15912
15913 oa->write_character(to_char_type(output_type));
15914 write_number(static_cast<std::uint32_t>(N));
15915 }
15916
15917 // step 1.5: if this is an ext type, write the subtype
15918 if (use_ext)
15919 {
15920 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15921 }
15922
15923 // step 2: write the byte string
15924 oa->write_characters(
15925 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15926 N);
15927
15928 break;
15929 }
15930
15931 case value_t::object:
15932 {
15933 // step 1: write control byte and the object size
15934 const auto N = j.m_data.m_value.object->size();
15935 if (N <= 15)
15936 {
15937 // fixmap
15938 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15939 }
15940 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15941 {
15942 // map 16
15943 oa->write_character(to_char_type(0xDE));
15944 write_number(static_cast<std::uint16_t>(N));
15945 }
15946 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15947 {
15948 // map 32
15949 oa->write_character(to_char_type(0xDF));
15950 write_number(static_cast<std::uint32_t>(N));
15951 }
15952
15953 // step 2: write each element
15954 for (const auto& el : *j.m_data.m_value.object)
15955 {
15956 write_msgpack(el.first);
15957 write_msgpack(el.second);
15958 }
15959 break;
15960 }
15961
15962 case value_t::discarded:
15963 default:
15964 break;
15965 }
15966 }
15967
15975 void write_ubjson(const BasicJsonType& j, const bool use_count,
15976 const bool use_type, const bool add_prefix = true,
15977 const bool use_bjdata = false)
15978 {
15979 switch (j.type())
15980 {
15981 case value_t::null:
15982 {
15983 if (add_prefix)
15984 {
15985 oa->write_character(to_char_type('Z'));
15986 }
15987 break;
15988 }
15989
15990 case value_t::boolean:
15991 {
15992 if (add_prefix)
15993 {
15994 oa->write_character(j.m_data.m_value.boolean
15995 ? to_char_type('T')
15996 : to_char_type('F'));
15997 }
15998 break;
15999 }
16000
16001 case value_t::number_integer:
16002 {
16003 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16004 break;
16005 }
16006
16007 case value_t::number_unsigned:
16008 {
16009 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16010 break;
16011 }
16012
16013 case value_t::number_float:
16014 {
16015 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16016 break;
16017 }
16018
16019 case value_t::string:
16020 {
16021 if (add_prefix)
16022 {
16023 oa->write_character(to_char_type('S'));
16024 }
16025 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16026 oa->write_characters(
16027 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16028 j.m_data.m_value.string->size());
16029 break;
16030 }
16031
16032 case value_t::array:
16033 {
16034 if (add_prefix)
16035 {
16036 oa->write_character(to_char_type('['));
16037 }
16038
16039 bool prefix_required = true;
16040 if (use_type && !j.m_data.m_value.array->empty())
16041 {
16042 JSON_ASSERT(use_count);
16043 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16044 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16045 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16046 {
16047 return ubjson_prefix(v, use_bjdata) == first_prefix;
16048 });
16049
16050 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16051
16052 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16053 {
16054 prefix_required = false;
16055 oa->write_character(to_char_type('$'));
16056 oa->write_character(first_prefix);
16057 }
16058 }
16059
16060 if (use_count)
16061 {
16062 oa->write_character(to_char_type('#'));
16063 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16064 }
16065
16066 for (const auto& el : *j.m_data.m_value.array)
16067 {
16068 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
16069 }
16070
16071 if (!use_count)
16072 {
16073 oa->write_character(to_char_type(']'));
16074 }
16075
16076 break;
16077 }
16078
16079 case value_t::binary:
16080 {
16081 if (add_prefix)
16082 {
16083 oa->write_character(to_char_type('['));
16084 }
16085
16086 if (use_type && !j.m_data.m_value.binary->empty())
16087 {
16088 JSON_ASSERT(use_count);
16089 oa->write_character(to_char_type('$'));
16090 oa->write_character('U');
16091 }
16092
16093 if (use_count)
16094 {
16095 oa->write_character(to_char_type('#'));
16096 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16097 }
16098
16099 if (use_type)
16100 {
16101 oa->write_characters(
16102 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16103 j.m_data.m_value.binary->size());
16104 }
16105 else
16106 {
16107 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16108 {
16109 oa->write_character(to_char_type('U'));
16110 oa->write_character(j.m_data.m_value.binary->data()[i]);
16111 }
16112 }
16113
16114 if (!use_count)
16115 {
16116 oa->write_character(to_char_type(']'));
16117 }
16118
16119 break;
16120 }
16121
16122 case value_t::object:
16123 {
16124 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
16125 {
16126 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
16127 {
16128 break;
16129 }
16130 }
16131
16132 if (add_prefix)
16133 {
16134 oa->write_character(to_char_type('{'));
16135 }
16136
16137 bool prefix_required = true;
16138 if (use_type && !j.m_data.m_value.object->empty())
16139 {
16140 JSON_ASSERT(use_count);
16141 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16142 const bool same_prefix = std::all_of(j.begin(), j.end(),
16143 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16144 {
16145 return ubjson_prefix(v, use_bjdata) == first_prefix;
16146 });
16147
16148 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16149
16150 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16151 {
16152 prefix_required = false;
16153 oa->write_character(to_char_type('$'));
16154 oa->write_character(first_prefix);
16155 }
16156 }
16157
16158 if (use_count)
16159 {
16160 oa->write_character(to_char_type('#'));
16161 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16162 }
16163
16164 for (const auto& el : *j.m_data.m_value.object)
16165 {
16166 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16167 oa->write_characters(
16168 reinterpret_cast<const CharType*>(el.first.c_str()),
16169 el.first.size());
16170 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
16171 }
16172
16173 if (!use_count)
16174 {
16175 oa->write_character(to_char_type('}'));
16176 }
16177
16178 break;
16179 }
16180
16181 case value_t::discarded:
16182 default:
16183 break;
16184 }
16185 }
16186
16187 private:
16189 // BSON //
16191
16196 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16197 {
16198 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16199 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16200 {
16201 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16202 static_cast<void>(j);
16203 }
16204
16205 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16206 }
16207
16211 void write_bson_entry_header(const string_t& name,
16212 const std::uint8_t element_type)
16213 {
16214 oa->write_character(to_char_type(element_type)); // boolean
16215 oa->write_characters(
16216 reinterpret_cast<const CharType*>(name.c_str()),
16217 name.size() + 1u);
16218 }
16219
16223 void write_bson_boolean(const string_t& name,
16224 const bool value)
16225 {
16226 write_bson_entry_header(name, 0x08);
16227 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16228 }
16229
16233 void write_bson_double(const string_t& name,
16234 const double value)
16235 {
16236 write_bson_entry_header(name, 0x01);
16237 write_number<double>(value, true);
16238 }
16239
16243 static std::size_t calc_bson_string_size(const string_t& value)
16244 {
16245 return sizeof(std::int32_t) + value.size() + 1ul;
16246 }
16247
16251 void write_bson_string(const string_t& name,
16252 const string_t& value)
16253 {
16254 write_bson_entry_header(name, 0x02);
16255
16256 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16257 oa->write_characters(
16258 reinterpret_cast<const CharType*>(value.c_str()),
16259 value.size() + 1);
16260 }
16261
16265 void write_bson_null(const string_t& name)
16266 {
16267 write_bson_entry_header(name, 0x0A);
16268 }
16269
16273 static std::size_t calc_bson_integer_size(const std::int64_t value)
16274 {
16275 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16276 ? sizeof(std::int32_t)
16277 : sizeof(std::int64_t);
16278 }
16279
16283 void write_bson_integer(const string_t& name,
16284 const std::int64_t value)
16285 {
16286 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16287 {
16288 write_bson_entry_header(name, 0x10); // int32
16289 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16290 }
16291 else
16292 {
16293 write_bson_entry_header(name, 0x12); // int64
16294 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16295 }
16296 }
16297
16301 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16302 {
16303 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16304 ? sizeof(std::int32_t)
16305 : sizeof(std::int64_t);
16306 }
16307
16311 void write_bson_unsigned(const string_t& name,
16312 const BasicJsonType& j)
16313 {
16314 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16315 {
16316 write_bson_entry_header(name, 0x10 /* int32 */);
16317 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16318 }
16319 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16320 {
16321 write_bson_entry_header(name, 0x12 /* int64 */);
16322 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16323 }
16324 else
16325 {
16326 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16327 }
16328 }
16329
16333 void write_bson_object_entry(const string_t& name,
16334 const typename BasicJsonType::object_t& value)
16335 {
16336 write_bson_entry_header(name, 0x03); // object
16337 write_bson_object(value);
16338 }
16339
16343 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16344 {
16345 std::size_t array_index = 0ul;
16346
16347 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
16348 {
16349 return result + calc_bson_element_size(std::to_string(array_index++), el);
16350 });
16351
16352 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16353 }
16354
16358 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16359 {
16360 return sizeof(std::int32_t) + value.size() + 1ul;
16361 }
16362
16366 void write_bson_array(const string_t& name,
16367 const typename BasicJsonType::array_t& value)
16368 {
16369 write_bson_entry_header(name, 0x04); // array
16370 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16371
16372 std::size_t array_index = 0ul;
16373
16374 for (const auto& el : value)
16375 {
16376 write_bson_element(std::to_string(array_index++), el);
16377 }
16378
16379 oa->write_character(to_char_type(0x00));
16380 }
16381
16385 void write_bson_binary(const string_t& name,
16386 const binary_t& value)
16387 {
16388 write_bson_entry_header(name, 0x05);
16389
16390 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16391 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16392
16393 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16394 }
16395
16400 static std::size_t calc_bson_element_size(const string_t& name,
16401 const BasicJsonType& j)
16402 {
16403 const auto header_size = calc_bson_entry_header_size(name, j);
16404 switch (j.type())
16405 {
16406 case value_t::object:
16407 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16408
16409 case value_t::array:
16410 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16411
16412 case value_t::binary:
16413 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16414
16415 case value_t::boolean:
16416 return header_size + 1ul;
16417
16418 case value_t::number_float:
16419 return header_size + 8ul;
16420
16421 case value_t::number_integer:
16422 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16423
16424 case value_t::number_unsigned:
16425 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16426
16427 case value_t::string:
16428 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16429
16430 case value_t::null:
16431 return header_size + 0ul;
16432
16433 // LCOV_EXCL_START
16434 case value_t::discarded:
16435 default:
16436 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16437 return 0ul;
16438 // LCOV_EXCL_STOP
16439 }
16440 }
16441
16448 void write_bson_element(const string_t& name,
16449 const BasicJsonType& j)
16450 {
16451 switch (j.type())
16452 {
16453 case value_t::object:
16454 return write_bson_object_entry(name, *j.m_data.m_value.object);
16455
16456 case value_t::array:
16457 return write_bson_array(name, *j.m_data.m_value.array);
16458
16459 case value_t::binary:
16460 return write_bson_binary(name, *j.m_data.m_value.binary);
16461
16462 case value_t::boolean:
16463 return write_bson_boolean(name, j.m_data.m_value.boolean);
16464
16465 case value_t::number_float:
16466 return write_bson_double(name, j.m_data.m_value.number_float);
16467
16468 case value_t::number_integer:
16469 return write_bson_integer(name, j.m_data.m_value.number_integer);
16470
16471 case value_t::number_unsigned:
16472 return write_bson_unsigned(name, j);
16473
16474 case value_t::string:
16475 return write_bson_string(name, *j.m_data.m_value.string);
16476
16477 case value_t::null:
16478 return write_bson_null(name);
16479
16480 // LCOV_EXCL_START
16481 case value_t::discarded:
16482 default:
16483 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16484 return;
16485 // LCOV_EXCL_STOP
16486 }
16487 }
16488
16495 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16496 {
16497 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16498 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16499 {
16500 return result += calc_bson_element_size(el.first, el.second);
16501 });
16502
16503 return sizeof(std::int32_t) + document_size + 1ul;
16504 }
16505
16510 void write_bson_object(const typename BasicJsonType::object_t& value)
16511 {
16512 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16513
16514 for (const auto& el : value)
16515 {
16516 write_bson_element(el.first, el.second);
16517 }
16518
16519 oa->write_character(to_char_type(0x00));
16520 }
16521
16523 // CBOR //
16525
16526 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16527 {
16528 return to_char_type(0xFA); // Single-Precision Float
16529 }
16530
16531 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16532 {
16533 return to_char_type(0xFB); // Double-Precision Float
16534 }
16535
16537 // MsgPack //
16539
16540 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16541 {
16542 return to_char_type(0xCA); // float 32
16543 }
16544
16545 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16546 {
16547 return to_char_type(0xCB); // float 64
16548 }
16549
16551 // UBJSON //
16553
16554 // UBJSON: write number (floating point)
16555 template<typename NumberType, typename std::enable_if<
16556 std::is_floating_point<NumberType>::value, int>::type = 0>
16557 void write_number_with_ubjson_prefix(const NumberType n,
16558 const bool add_prefix,
16559 const bool use_bjdata)
16560 {
16561 if (add_prefix)
16562 {
16563 oa->write_character(get_ubjson_float_prefix(n));
16564 }
16565 write_number(n, use_bjdata);
16566 }
16567
16568 // UBJSON: write number (unsigned integer)
16569 template<typename NumberType, typename std::enable_if<
16570 std::is_unsigned<NumberType>::value, int>::type = 0>
16571 void write_number_with_ubjson_prefix(const NumberType n,
16572 const bool add_prefix,
16573 const bool use_bjdata)
16574 {
16575 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16576 {
16577 if (add_prefix)
16578 {
16579 oa->write_character(to_char_type('i')); // int8
16580 }
16581 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16582 }
16583 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16584 {
16585 if (add_prefix)
16586 {
16587 oa->write_character(to_char_type('U')); // uint8
16588 }
16589 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16590 }
16591 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16592 {
16593 if (add_prefix)
16594 {
16595 oa->write_character(to_char_type('I')); // int16
16596 }
16597 write_number(static_cast<std::int16_t>(n), use_bjdata);
16598 }
16599 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16600 {
16601 if (add_prefix)
16602 {
16603 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16604 }
16605 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16606 }
16607 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16608 {
16609 if (add_prefix)
16610 {
16611 oa->write_character(to_char_type('l')); // int32
16612 }
16613 write_number(static_cast<std::int32_t>(n), use_bjdata);
16614 }
16615 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16616 {
16617 if (add_prefix)
16618 {
16619 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16620 }
16621 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16622 }
16623 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16624 {
16625 if (add_prefix)
16626 {
16627 oa->write_character(to_char_type('L')); // int64
16628 }
16629 write_number(static_cast<std::int64_t>(n), use_bjdata);
16630 }
16631 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16632 {
16633 if (add_prefix)
16634 {
16635 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16636 }
16637 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16638 }
16639 else
16640 {
16641 if (add_prefix)
16642 {
16643 oa->write_character(to_char_type('H')); // high-precision number
16644 }
16645
16646 const auto number = BasicJsonType(n).dump();
16647 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16648 for (std::size_t i = 0; i < number.size(); ++i)
16649 {
16650 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16651 }
16652 }
16653 }
16654
16655 // UBJSON: write number (signed integer)
16656 template < typename NumberType, typename std::enable_if <
16657 std::is_signed<NumberType>::value&&
16658 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16659 void write_number_with_ubjson_prefix(const NumberType n,
16660 const bool add_prefix,
16661 const bool use_bjdata)
16662 {
16663 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16664 {
16665 if (add_prefix)
16666 {
16667 oa->write_character(to_char_type('i')); // int8
16668 }
16669 write_number(static_cast<std::int8_t>(n), use_bjdata);
16670 }
16671 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
16672 {
16673 if (add_prefix)
16674 {
16675 oa->write_character(to_char_type('U')); // uint8
16676 }
16677 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16678 }
16679 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16680 {
16681 if (add_prefix)
16682 {
16683 oa->write_character(to_char_type('I')); // int16
16684 }
16685 write_number(static_cast<std::int16_t>(n), use_bjdata);
16686 }
16687 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
16688 {
16689 if (add_prefix)
16690 {
16691 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16692 }
16693 write_number(static_cast<uint16_t>(n), use_bjdata);
16694 }
16695 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16696 {
16697 if (add_prefix)
16698 {
16699 oa->write_character(to_char_type('l')); // int32
16700 }
16701 write_number(static_cast<std::int32_t>(n), use_bjdata);
16702 }
16703 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
16704 {
16705 if (add_prefix)
16706 {
16707 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16708 }
16709 write_number(static_cast<uint32_t>(n), use_bjdata);
16710 }
16711 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16712 {
16713 if (add_prefix)
16714 {
16715 oa->write_character(to_char_type('L')); // int64
16716 }
16717 write_number(static_cast<std::int64_t>(n), use_bjdata);
16718 }
16719 // LCOV_EXCL_START
16720 else
16721 {
16722 if (add_prefix)
16723 {
16724 oa->write_character(to_char_type('H')); // high-precision number
16725 }
16726
16727 const auto number = BasicJsonType(n).dump();
16728 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16729 for (std::size_t i = 0; i < number.size(); ++i)
16730 {
16731 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16732 }
16733 }
16734 // LCOV_EXCL_STOP
16735 }
16736
16740 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16741 {
16742 switch (j.type())
16743 {
16744 case value_t::null:
16745 return 'Z';
16746
16747 case value_t::boolean:
16748 return j.m_data.m_value.boolean ? 'T' : 'F';
16749
16750 case value_t::number_integer:
16751 {
16752 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16753 {
16754 return 'i';
16755 }
16756 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16757 {
16758 return 'U';
16759 }
16760 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16761 {
16762 return 'I';
16763 }
16764 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16765 {
16766 return 'u';
16767 }
16768 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16769 {
16770 return 'l';
16771 }
16772 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16773 {
16774 return 'm';
16775 }
16776 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16777 {
16778 return 'L';
16779 }
16780 // anything else is treated as high-precision number
16781 return 'H'; // LCOV_EXCL_LINE
16782 }
16783
16784 case value_t::number_unsigned:
16785 {
16786 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16787 {
16788 return 'i';
16789 }
16790 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16791 {
16792 return 'U';
16793 }
16794 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16795 {
16796 return 'I';
16797 }
16798 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16799 {
16800 return 'u';
16801 }
16802 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16803 {
16804 return 'l';
16805 }
16806 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16807 {
16808 return 'm';
16809 }
16810 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16811 {
16812 return 'L';
16813 }
16814 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16815 {
16816 return 'M';
16817 }
16818 // anything else is treated as high-precision number
16819 return 'H'; // LCOV_EXCL_LINE
16820 }
16821
16822 case value_t::number_float:
16823 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16824
16825 case value_t::string:
16826 return 'S';
16827
16828 case value_t::array: // fallthrough
16829 case value_t::binary:
16830 return '[';
16831
16832 case value_t::object:
16833 return '{';
16834
16835 case value_t::discarded:
16836 default: // discarded values
16837 return 'N';
16838 }
16839 }
16840
16841 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16842 {
16843 return 'd'; // float 32
16844 }
16845
16846 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16847 {
16848 return 'D'; // float 64
16849 }
16850
16854 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16855 {
16856 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16857 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16858 };
16859
16860 string_t key = "_ArrayType_";
16861 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16862 if (it == bjdtype.end())
16863 {
16864 return true;
16865 }
16866 CharType dtype = it->second;
16867
16868 key = "_ArraySize_";
16869 std::size_t len = (value.at(key).empty() ? 0 : 1);
16870 for (const auto& el : value.at(key))
16871 {
16872 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16873 }
16874
16875 key = "_ArrayData_";
16876 if (value.at(key).size() != len)
16877 {
16878 return true;
16879 }
16880
16881 oa->write_character('[');
16882 oa->write_character('$');
16883 oa->write_character(dtype);
16884 oa->write_character('#');
16885
16886 key = "_ArraySize_";
16887 write_ubjson(value.at(key), use_count, use_type, true, true);
16888
16889 key = "_ArrayData_";
16890 if (dtype == 'U' || dtype == 'C')
16891 {
16892 for (const auto& el : value.at(key))
16893 {
16894 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16895 }
16896 }
16897 else if (dtype == 'i')
16898 {
16899 for (const auto& el : value.at(key))
16900 {
16901 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16902 }
16903 }
16904 else if (dtype == 'u')
16905 {
16906 for (const auto& el : value.at(key))
16907 {
16908 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16909 }
16910 }
16911 else if (dtype == 'I')
16912 {
16913 for (const auto& el : value.at(key))
16914 {
16915 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16916 }
16917 }
16918 else if (dtype == 'm')
16919 {
16920 for (const auto& el : value.at(key))
16921 {
16922 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16923 }
16924 }
16925 else if (dtype == 'l')
16926 {
16927 for (const auto& el : value.at(key))
16928 {
16929 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16930 }
16931 }
16932 else if (dtype == 'M')
16933 {
16934 for (const auto& el : value.at(key))
16935 {
16936 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16937 }
16938 }
16939 else if (dtype == 'L')
16940 {
16941 for (const auto& el : value.at(key))
16942 {
16943 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16944 }
16945 }
16946 else if (dtype == 'd')
16947 {
16948 for (const auto& el : value.at(key))
16949 {
16950 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16951 }
16952 }
16953 else if (dtype == 'D')
16954 {
16955 for (const auto& el : value.at(key))
16956 {
16957 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16958 }
16959 }
16960 return false;
16961 }
16962
16964 // Utility functions //
16966
16967 /*
16968 @brief write a number to output input
16969 @param[in] n number of type @a NumberType
16970 @param[in] OutputIsLittleEndian Set to true if output data is
16971 required to be little endian
16972 @tparam NumberType the type of the number
16973
16974 @note This function needs to respect the system's endianness, because bytes
16975 in CBOR, MessagePack, and UBJSON are stored in network order (big
16976 endian) and therefore need reordering on little endian systems.
16977 On the other hand, BSON and BJData use little endian and should reorder
16978 on big endian systems.
16979 */
16980 template<typename NumberType>
16981 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16982 {
16983 // step 1: write number to array of length NumberType
16984 std::array<CharType, sizeof(NumberType)> vec{};
16985 std::memcpy(vec.data(), &n, sizeof(NumberType));
16986
16987 // step 2: write array to output (with possible reordering)
16988 if (is_little_endian != OutputIsLittleEndian)
16989 {
16990 // reverse byte order prior to conversion if necessary
16991 std::reverse(vec.begin(), vec.end());
16992 }
16993
16994 oa->write_characters(vec.data(), sizeof(NumberType));
16995 }
16996
16997 void write_compact_float(const number_float_t n, detail::input_format_t format)
16998 {
16999#ifdef __GNUC__
17000#pragma GCC diagnostic push
17001#pragma GCC diagnostic ignored "-Wfloat-equal"
17002#endif
17003 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17004 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17005 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
17006 {
17007 oa->write_character(format == detail::input_format_t::cbor
17008 ? get_cbor_float_prefix(static_cast<float>(n))
17009 : get_msgpack_float_prefix(static_cast<float>(n)));
17010 write_number(static_cast<float>(n));
17011 }
17012 else
17013 {
17014 oa->write_character(format == detail::input_format_t::cbor
17015 ? get_cbor_float_prefix(n)
17016 : get_msgpack_float_prefix(n));
17017 write_number(n);
17018 }
17019#ifdef __GNUC__
17020#pragma GCC diagnostic pop
17021#endif
17022 }
17023
17024 public:
17025 // The following to_char_type functions are implement the conversion
17026 // between uint8_t and CharType. In case CharType is not unsigned,
17027 // such a conversion is required to allow values greater than 128.
17028 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17029 template < typename C = CharType,
17030 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17031 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17032 {
17033 return *reinterpret_cast<char*>(&x);
17034 }
17035
17036 template < typename C = CharType,
17037 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17038 static CharType to_char_type(std::uint8_t x) noexcept
17039 {
17040 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17041 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17042 CharType result;
17043 std::memcpy(&result, &x, sizeof(x));
17044 return result;
17045 }
17046
17047 template<typename C = CharType,
17048 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
17049 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17050 {
17051 return x;
17052 }
17053
17054 template < typename InputCharType, typename C = CharType,
17055 enable_if_t <
17056 std::is_signed<C>::value &&
17057 std::is_signed<char>::value &&
17058 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17059 > * = nullptr >
17060 static constexpr CharType to_char_type(InputCharType x) noexcept
17061 {
17062 return x;
17063 }
17064
17065 private:
17067 const bool is_little_endian = little_endianness();
17068
17070 output_adapter_t<CharType> oa = nullptr;
17071};
17072
17073} // namespace detail
17075
17076// #include <nlohmann/detail/output/output_adapters.hpp>
17077
17078// #include <nlohmann/detail/output/serializer.hpp>
17079// __ _____ _____ _____
17080// __| | __| | | | JSON for Modern C++
17081// | | |__ | | | | | | version 3.11.3
17082// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17083//
17084// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17085// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
17086// SPDX-License-Identifier: MIT
17087
17088
17089
17090#include <algorithm> // reverse, remove, fill, find, none_of
17091#include <array> // array
17092#include <clocale> // localeconv, lconv
17093#include <cmath> // labs, isfinite, isnan, signbit
17094#include <cstddef> // size_t, ptrdiff_t
17095#include <cstdint> // uint8_t
17096#include <cstdio> // snprintf
17097#include <limits> // numeric_limits
17098#include <string> // string, char_traits
17099#include <iomanip> // setfill, setw
17100#include <type_traits> // is_same
17101#include <utility> // move
17102
17103// #include <nlohmann/detail/conversions/to_chars.hpp>
17104// __ _____ _____ _____
17105// __| | __| | | | JSON for Modern C++
17106// | | |__ | | | | | | version 3.11.3
17107// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17108//
17109// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17110// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
17111// SPDX-License-Identifier: MIT
17112
17113
17114
17115#include <array> // array
17116#include <cmath> // signbit, isfinite
17117#include <cstdint> // intN_t, uintN_t
17118#include <cstring> // memcpy, memmove
17119#include <limits> // numeric_limits
17120#include <type_traits> // conditional
17121
17122// #include <nlohmann/detail/macro_scope.hpp>
17123
17124
17126namespace detail
17127{
17128
17148namespace dtoa_impl
17149{
17150
17151template<typename Target, typename Source>
17152Target reinterpret_bits(const Source source)
17153{
17154 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17155
17156 Target target;
17157 std::memcpy(&target, &source, sizeof(Source));
17158 return target;
17159}
17160
17161struct diyfp // f * 2^e
17162{
17163 static constexpr int kPrecision = 64; // = q
17164
17165 std::uint64_t f = 0;
17166 int e = 0;
17167
17168 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17169
17174 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17175 {
17176 JSON_ASSERT(x.e == y.e);
17177 JSON_ASSERT(x.f >= y.f);
17178
17179 return {x.f - y.f, x.e};
17180 }
17181
17186 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17187 {
17188 static_assert(kPrecision == 64, "internal error");
17189
17190 // Computes:
17191 // f = round((x.f * y.f) / 2^q)
17192 // e = x.e + y.e + q
17193
17194 // Emulate the 64-bit * 64-bit multiplication:
17195 //
17196 // p = u * v
17197 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17198 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17199 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17200 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17201 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17202 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17203 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17204 //
17205 // (Since Q might be larger than 2^32 - 1)
17206 //
17207 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17208 //
17209 // (Q_hi + H does not overflow a 64-bit int)
17210 //
17211 // = p_lo + 2^64 p_hi
17212
17213 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17214 const std::uint64_t u_hi = x.f >> 32u;
17215 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17216 const std::uint64_t v_hi = y.f >> 32u;
17217
17218 const std::uint64_t p0 = u_lo * v_lo;
17219 const std::uint64_t p1 = u_lo * v_hi;
17220 const std::uint64_t p2 = u_hi * v_lo;
17221 const std::uint64_t p3 = u_hi * v_hi;
17222
17223 const std::uint64_t p0_hi = p0 >> 32u;
17224 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17225 const std::uint64_t p1_hi = p1 >> 32u;
17226 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17227 const std::uint64_t p2_hi = p2 >> 32u;
17228
17229 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17230
17231 // The full product might now be computed as
17232 //
17233 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17234 // p_lo = p0_lo + (Q << 32)
17235 //
17236 // But in this particular case here, the full p_lo is not required.
17237 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17238 // Q_hi + 1 does not overflow).
17239
17240 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17241
17242 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17243
17244 return {h, x.e + y.e + 64};
17245 }
17246
17251 static diyfp normalize(diyfp x) noexcept
17252 {
17253 JSON_ASSERT(x.f != 0);
17254
17255 while ((x.f >> 63u) == 0)
17256 {
17257 x.f <<= 1u;
17258 x.e--;
17259 }
17260
17261 return x;
17262 }
17263
17268 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17269 {
17270 const int delta = x.e - target_exponent;
17271
17272 JSON_ASSERT(delta >= 0);
17273 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17274
17275 return {x.f << delta, target_exponent};
17276 }
17277};
17278
17279struct boundaries
17280{
17281 diyfp w;
17282 diyfp minus;
17283 diyfp plus;
17284};
17285
17292template<typename FloatType>
17293boundaries compute_boundaries(FloatType value)
17294{
17295 JSON_ASSERT(std::isfinite(value));
17296 JSON_ASSERT(value > 0);
17297
17298 // Convert the IEEE representation into a diyfp.
17299 //
17300 // If v is denormal:
17301 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17302 // If v is normalized:
17303 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17304
17305 static_assert(std::numeric_limits<FloatType>::is_iec559,
17306 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17307
17308 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17309 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17310 constexpr int kMinExp = 1 - kBias;
17311 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17312
17313 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17314
17315 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17316 const std::uint64_t E = bits >> (kPrecision - 1);
17317 const std::uint64_t F = bits & (kHiddenBit - 1);
17318
17319 const bool is_denormal = E == 0;
17320 const diyfp v = is_denormal
17321 ? diyfp(F, kMinExp)
17322 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17323
17324 // Compute the boundaries m- and m+ of the floating-point value
17325 // v = f * 2^e.
17326 //
17327 // Determine v- and v+, the floating-point predecessor and successor if v,
17328 // respectively.
17329 //
17330 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17331 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17332 //
17333 // v+ = v + 2^e
17334 //
17335 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17336 // between m- and m+ round to v, regardless of how the input rounding
17337 // algorithm breaks ties.
17338 //
17339 // ---+-------------+-------------+-------------+-------------+--- (A)
17340 // v- m- v m+ v+
17341 //
17342 // -----------------+------+------+-------------+-------------+--- (B)
17343 // v- m- v m+ v+
17344
17345 const bool lower_boundary_is_closer = F == 0 && E > 1;
17346 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17347 const diyfp m_minus = lower_boundary_is_closer
17348 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17349 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17350
17351 // Determine the normalized w+ = m+.
17352 const diyfp w_plus = diyfp::normalize(m_plus);
17353
17354 // Determine w- = m- such that e_(w-) = e_(w+).
17355 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17356
17357 return {diyfp::normalize(v), w_minus, w_plus};
17358}
17359
17360// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17361// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17362// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17363//
17364// alpha <= e = e_c + e_w + q <= gamma
17365//
17366// or
17367//
17368// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17369// <= f_c * f_w * 2^gamma
17370//
17371// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17372//
17373// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17374//
17375// or
17376//
17377// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17378//
17379// The choice of (alpha,gamma) determines the size of the table and the form of
17380// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17381// in practice:
17382//
17383// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17384// processed independently: An integral part p1, and a fractional part p2:
17385//
17386// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17387// = (f div 2^-e) + (f mod 2^-e) * 2^e
17388// = p1 + p2 * 2^e
17389//
17390// The conversion of p1 into decimal form requires a series of divisions and
17391// modulos by (a power of) 10. These operations are faster for 32-bit than for
17392// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17393// achieved by choosing
17394//
17395// -e >= 32 or e <= -32 := gamma
17396//
17397// In order to convert the fractional part
17398//
17399// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17400//
17401// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17402// d[-i] are extracted in order:
17403//
17404// (10 * p2) div 2^-e = d[-1]
17405// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17406//
17407// The multiplication by 10 must not overflow. It is sufficient to choose
17408//
17409// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17410//
17411// Since p2 = f mod 2^-e < 2^-e,
17412//
17413// -e <= 60 or e >= -60 := alpha
17414
17415constexpr int kAlpha = -60;
17416constexpr int kGamma = -32;
17417
17418struct cached_power // c = f * 2^e ~= 10^k
17419{
17420 std::uint64_t f;
17421 int e;
17422 int k;
17423};
17424
17432inline cached_power get_cached_power_for_binary_exponent(int e)
17433{
17434 // Now
17435 //
17436 // alpha <= e_c + e + q <= gamma (1)
17437 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17438 //
17439 // and since the c's are normalized, 2^(q-1) <= f_c,
17440 //
17441 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17442 // ==> 2^(alpha - e - 1) <= c
17443 //
17444 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17445 //
17446 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17447 // = ceil( (alpha - e - 1) * log_10(2) )
17448 //
17449 // From the paper:
17450 // "In theory the result of the procedure could be wrong since c is rounded,
17451 // and the computation itself is approximated [...]. In practice, however,
17452 // this simple function is sufficient."
17453 //
17454 // For IEEE double precision floating-point numbers converted into
17455 // normalized diyfp's w = f * 2^e, with q = 64,
17456 //
17457 // e >= -1022 (min IEEE exponent)
17458 // -52 (p - 1)
17459 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17460 // -11 (normalize the diyfp)
17461 // = -1137
17462 //
17463 // and
17464 //
17465 // e <= +1023 (max IEEE exponent)
17466 // -52 (p - 1)
17467 // -11 (normalize the diyfp)
17468 // = 960
17469 //
17470 // This binary exponent range [-1137,960] results in a decimal exponent
17471 // range [-307,324]. One does not need to store a cached power for each
17472 // k in this range. For each such k it suffices to find a cached power
17473 // such that the exponent of the product lies in [alpha,gamma].
17474 // This implies that the difference of the decimal exponents of adjacent
17475 // table entries must be less than or equal to
17476 //
17477 // floor( (gamma - alpha) * log_10(2) ) = 8.
17478 //
17479 // (A smaller distance gamma-alpha would require a larger table.)
17480
17481 // NB:
17482 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17483
17484 constexpr int kCachedPowersMinDecExp = -300;
17485 constexpr int kCachedPowersDecStep = 8;
17486
17487 static constexpr std::array<cached_power, 79> kCachedPowers =
17488 {
17489 {
17490 { 0xAB70FE17C79AC6CA, -1060, -300 },
17491 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17492 { 0xBE5691EF416BD60C, -1007, -284 },
17493 { 0x8DD01FAD907FFC3C, -980, -276 },
17494 { 0xD3515C2831559A83, -954, -268 },
17495 { 0x9D71AC8FADA6C9B5, -927, -260 },
17496 { 0xEA9C227723EE8BCB, -901, -252 },
17497 { 0xAECC49914078536D, -874, -244 },
17498 { 0x823C12795DB6CE57, -847, -236 },
17499 { 0xC21094364DFB5637, -821, -228 },
17500 { 0x9096EA6F3848984F, -794, -220 },
17501 { 0xD77485CB25823AC7, -768, -212 },
17502 { 0xA086CFCD97BF97F4, -741, -204 },
17503 { 0xEF340A98172AACE5, -715, -196 },
17504 { 0xB23867FB2A35B28E, -688, -188 },
17505 { 0x84C8D4DFD2C63F3B, -661, -180 },
17506 { 0xC5DD44271AD3CDBA, -635, -172 },
17507 { 0x936B9FCEBB25C996, -608, -164 },
17508 { 0xDBAC6C247D62A584, -582, -156 },
17509 { 0xA3AB66580D5FDAF6, -555, -148 },
17510 { 0xF3E2F893DEC3F126, -529, -140 },
17511 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17512 { 0x87625F056C7C4A8B, -475, -124 },
17513 { 0xC9BCFF6034C13053, -449, -116 },
17514 { 0x964E858C91BA2655, -422, -108 },
17515 { 0xDFF9772470297EBD, -396, -100 },
17516 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17517 { 0xF8A95FCF88747D94, -343, -84 },
17518 { 0xB94470938FA89BCF, -316, -76 },
17519 { 0x8A08F0F8BF0F156B, -289, -68 },
17520 { 0xCDB02555653131B6, -263, -60 },
17521 { 0x993FE2C6D07B7FAC, -236, -52 },
17522 { 0xE45C10C42A2B3B06, -210, -44 },
17523 { 0xAA242499697392D3, -183, -36 },
17524 { 0xFD87B5F28300CA0E, -157, -28 },
17525 { 0xBCE5086492111AEB, -130, -20 },
17526 { 0x8CBCCC096F5088CC, -103, -12 },
17527 { 0xD1B71758E219652C, -77, -4 },
17528 { 0x9C40000000000000, -50, 4 },
17529 { 0xE8D4A51000000000, -24, 12 },
17530 { 0xAD78EBC5AC620000, 3, 20 },
17531 { 0x813F3978F8940984, 30, 28 },
17532 { 0xC097CE7BC90715B3, 56, 36 },
17533 { 0x8F7E32CE7BEA5C70, 83, 44 },
17534 { 0xD5D238A4ABE98068, 109, 52 },
17535 { 0x9F4F2726179A2245, 136, 60 },
17536 { 0xED63A231D4C4FB27, 162, 68 },
17537 { 0xB0DE65388CC8ADA8, 189, 76 },
17538 { 0x83C7088E1AAB65DB, 216, 84 },
17539 { 0xC45D1DF942711D9A, 242, 92 },
17540 { 0x924D692CA61BE758, 269, 100 },
17541 { 0xDA01EE641A708DEA, 295, 108 },
17542 { 0xA26DA3999AEF774A, 322, 116 },
17543 { 0xF209787BB47D6B85, 348, 124 },
17544 { 0xB454E4A179DD1877, 375, 132 },
17545 { 0x865B86925B9BC5C2, 402, 140 },
17546 { 0xC83553C5C8965D3D, 428, 148 },
17547 { 0x952AB45CFA97A0B3, 455, 156 },
17548 { 0xDE469FBD99A05FE3, 481, 164 },
17549 { 0xA59BC234DB398C25, 508, 172 },
17550 { 0xF6C69A72A3989F5C, 534, 180 },
17551 { 0xB7DCBF5354E9BECE, 561, 188 },
17552 { 0x88FCF317F22241E2, 588, 196 },
17553 { 0xCC20CE9BD35C78A5, 614, 204 },
17554 { 0x98165AF37B2153DF, 641, 212 },
17555 { 0xE2A0B5DC971F303A, 667, 220 },
17556 { 0xA8D9D1535CE3B396, 694, 228 },
17557 { 0xFB9B7CD9A4A7443C, 720, 236 },
17558 { 0xBB764C4CA7A44410, 747, 244 },
17559 { 0x8BAB8EEFB6409C1A, 774, 252 },
17560 { 0xD01FEF10A657842C, 800, 260 },
17561 { 0x9B10A4E5E9913129, 827, 268 },
17562 { 0xE7109BFBA19C0C9D, 853, 276 },
17563 { 0xAC2820D9623BF429, 880, 284 },
17564 { 0x80444B5E7AA7CF85, 907, 292 },
17565 { 0xBF21E44003ACDD2D, 933, 300 },
17566 { 0x8E679C2F5E44FF8F, 960, 308 },
17567 { 0xD433179D9C8CB841, 986, 316 },
17568 { 0x9E19DB92B4E31BA9, 1013, 324 },
17569 }
17570 };
17571
17572 // This computation gives exactly the same results for k as
17573 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17574 // for |e| <= 1500, but doesn't require floating-point operations.
17575 // NB: log_10(2) ~= 78913 / 2^18
17576 JSON_ASSERT(e >= -1500);
17577 JSON_ASSERT(e <= 1500);
17578 const int f = kAlpha - e - 1;
17579 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
17580
17581 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17582 JSON_ASSERT(index >= 0);
17583 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17584
17585 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17586 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17587 JSON_ASSERT(kGamma >= cached.e + e + 64);
17588
17589 return cached;
17590}
17591
17596inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17597{
17598 // LCOV_EXCL_START
17599 if (n >= 1000000000)
17600 {
17601 pow10 = 1000000000;
17602 return 10;
17603 }
17604 // LCOV_EXCL_STOP
17605 if (n >= 100000000)
17606 {
17607 pow10 = 100000000;
17608 return 9;
17609 }
17610 if (n >= 10000000)
17611 {
17612 pow10 = 10000000;
17613 return 8;
17614 }
17615 if (n >= 1000000)
17616 {
17617 pow10 = 1000000;
17618 return 7;
17619 }
17620 if (n >= 100000)
17621 {
17622 pow10 = 100000;
17623 return 6;
17624 }
17625 if (n >= 10000)
17626 {
17627 pow10 = 10000;
17628 return 5;
17629 }
17630 if (n >= 1000)
17631 {
17632 pow10 = 1000;
17633 return 4;
17634 }
17635 if (n >= 100)
17636 {
17637 pow10 = 100;
17638 return 3;
17639 }
17640 if (n >= 10)
17641 {
17642 pow10 = 10;
17643 return 2;
17644 }
17645
17646 pow10 = 1;
17647 return 1;
17648}
17649
17650inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17651 std::uint64_t rest, std::uint64_t ten_k)
17652{
17653 JSON_ASSERT(len >= 1);
17654 JSON_ASSERT(dist <= delta);
17655 JSON_ASSERT(rest <= delta);
17656 JSON_ASSERT(ten_k > 0);
17657
17658 // <--------------------------- delta ---->
17659 // <---- dist --------->
17660 // --------------[------------------+-------------------]--------------
17661 // M- w M+
17662 //
17663 // ten_k
17664 // <------>
17665 // <---- rest ---->
17666 // --------------[------------------+----+--------------]--------------
17667 // w V
17668 // = buf * 10^k
17669 //
17670 // ten_k represents a unit-in-the-last-place in the decimal representation
17671 // stored in buf.
17672 // Decrement buf by ten_k while this takes buf closer to w.
17673
17674 // The tests are written in this order to avoid overflow in unsigned
17675 // integer arithmetic.
17676
17677 while (rest < dist
17678 && delta - rest >= ten_k
17679 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17680 {
17681 JSON_ASSERT(buf[len - 1] != '0');
17682 buf[len - 1]--;
17683 rest += ten_k;
17684 }
17685}
17686
17691inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17692 diyfp M_minus, diyfp w, diyfp M_plus)
17693{
17694 static_assert(kAlpha >= -60, "internal error");
17695 static_assert(kGamma <= -32, "internal error");
17696
17697 // Generates the digits (and the exponent) of a decimal floating-point
17698 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17699 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17700 //
17701 // <--------------------------- delta ---->
17702 // <---- dist --------->
17703 // --------------[------------------+-------------------]--------------
17704 // M- w M+
17705 //
17706 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17707 // V is in [M-,M+].
17708
17709 JSON_ASSERT(M_plus.e >= kAlpha);
17710 JSON_ASSERT(M_plus.e <= kGamma);
17711
17712 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17713 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17714
17715 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17716 //
17717 // M+ = f * 2^e
17718 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17719 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17720 // = p1 + p2 * 2^e
17721
17722 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17723
17724 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
17725 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17726
17727 // 1)
17728 //
17729 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17730
17731 JSON_ASSERT(p1 > 0);
17732
17733 std::uint32_t pow10{};
17734 const int k = find_largest_pow10(p1, pow10);
17735
17736 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17737 //
17738 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17739 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17740 //
17741 // M+ = p1 + p2 * 2^e
17742 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17743 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17744 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17745 //
17746 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17747 //
17748 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17749 //
17750 // but stop as soon as
17751 //
17752 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17753
17754 int n = k;
17755 while (n > 0)
17756 {
17757 // Invariants:
17758 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17759 // pow10 = 10^(n-1) <= p1 < 10^n
17760 //
17761 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17762 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17763 //
17764 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17765 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17766 //
17767 JSON_ASSERT(d <= 9);
17768 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17769 //
17770 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17771 //
17772 p1 = r;
17773 n--;
17774 //
17775 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17776 // pow10 = 10^n
17777 //
17778
17779 // Now check if enough digits have been generated.
17780 // Compute
17781 //
17782 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17783 //
17784 // Note:
17785 // Since rest and delta share the same exponent e, it suffices to
17786 // compare the significands.
17787 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17788 if (rest <= delta)
17789 {
17790 // V = buffer * 10^n, with M- <= V <= M+.
17791
17792 decimal_exponent += n;
17793
17794 // We may now just stop. But instead look if the buffer could be
17795 // decremented to bring V closer to w.
17796 //
17797 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17798 // The rounding procedure works with diyfp's with an implicit
17799 // exponent of e.
17800 //
17801 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17802 //
17803 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17804 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17805
17806 return;
17807 }
17808
17809 pow10 /= 10;
17810 //
17811 // pow10 = 10^(n-1) <= p1 < 10^n
17812 // Invariants restored.
17813 }
17814
17815 // 2)
17816 //
17817 // The digits of the integral part have been generated:
17818 //
17819 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17820 // = buffer + p2 * 2^e
17821 //
17822 // Now generate the digits of the fractional part p2 * 2^e.
17823 //
17824 // Note:
17825 // No decimal point is generated: the exponent is adjusted instead.
17826 //
17827 // p2 actually represents the fraction
17828 //
17829 // p2 * 2^e
17830 // = p2 / 2^-e
17831 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17832 //
17833 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17834 //
17835 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17836 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17837 //
17838 // using
17839 //
17840 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17841 // = ( d) * 2^-e + ( r)
17842 //
17843 // or
17844 // 10^m * p2 * 2^e = d + r * 2^e
17845 //
17846 // i.e.
17847 //
17848 // M+ = buffer + p2 * 2^e
17849 // = buffer + 10^-m * (d + r * 2^e)
17850 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17851 //
17852 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17853
17854 JSON_ASSERT(p2 > delta);
17855
17856 int m = 0;
17857 for (;;)
17858 {
17859 // Invariant:
17860 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17861 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17862 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17863 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17864 //
17865 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17866 p2 *= 10;
17867 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17868 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17869 //
17870 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17871 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17872 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17873 //
17874 JSON_ASSERT(d <= 9);
17875 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17876 //
17877 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17878 //
17879 p2 = r;
17880 m++;
17881 //
17882 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17883 // Invariant restored.
17884
17885 // Check if enough digits have been generated.
17886 //
17887 // 10^-m * p2 * 2^e <= delta * 2^e
17888 // p2 * 2^e <= 10^m * delta * 2^e
17889 // p2 <= 10^m * delta
17890 delta *= 10;
17891 dist *= 10;
17892 if (p2 <= delta)
17893 {
17894 break;
17895 }
17896 }
17897
17898 // V = buffer * 10^-m, with M- <= V <= M+.
17899
17900 decimal_exponent -= m;
17901
17902 // 1 ulp in the decimal representation is now 10^-m.
17903 // Since delta and dist are now scaled by 10^m, we need to do the
17904 // same with ulp in order to keep the units in sync.
17905 //
17906 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17907 //
17908 const std::uint64_t ten_m = one.f;
17909 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17910
17911 // By construction this algorithm generates the shortest possible decimal
17912 // number (Loitsch, Theorem 6.2) which rounds back to w.
17913 // For an input number of precision p, at least
17914 //
17915 // N = 1 + ceil(p * log_10(2))
17916 //
17917 // decimal digits are sufficient to identify all binary floating-point
17918 // numbers (Matula, "In-and-Out conversions").
17919 // This implies that the algorithm does not produce more than N decimal
17920 // digits.
17921 //
17922 // N = 17 for p = 53 (IEEE double precision)
17923 // N = 9 for p = 24 (IEEE single precision)
17924}
17925
17932inline void grisu2(char* buf, int& len, int& decimal_exponent,
17933 diyfp m_minus, diyfp v, diyfp m_plus)
17934{
17935 JSON_ASSERT(m_plus.e == m_minus.e);
17936 JSON_ASSERT(m_plus.e == v.e);
17937
17938 // --------(-----------------------+-----------------------)-------- (A)
17939 // m- v m+
17940 //
17941 // --------------------(-----------+-----------------------)-------- (B)
17942 // m- v m+
17943 //
17944 // First scale v (and m- and m+) such that the exponent is in the range
17945 // [alpha, gamma].
17946
17947 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17948
17949 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17950
17951 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17952 const diyfp w = diyfp::mul(v, c_minus_k);
17953 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17954 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17955
17956 // ----(---+---)---------------(---+---)---------------(---+---)----
17957 // w- w w+
17958 // = c*m- = c*v = c*m+
17959 //
17960 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17961 // w+ are now off by a small amount.
17962 // In fact:
17963 //
17964 // w - v * 10^k < 1 ulp
17965 //
17966 // To account for this inaccuracy, add resp. subtract 1 ulp.
17967 //
17968 // --------+---[---------------(---+---)---------------]---+--------
17969 // w- M- w M+ w+
17970 //
17971 // Now any number in [M-, M+] (bounds included) will round to w when input,
17972 // regardless of how the input rounding algorithm breaks ties.
17973 //
17974 // And digit_gen generates the shortest possible such number in [M-, M+].
17975 // Note that this does not mean that Grisu2 always generates the shortest
17976 // possible number in the interval (m-, m+).
17977 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17978 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17979
17980 decimal_exponent = -cached.k; // = -(-k) = k
17981
17982 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17983}
17984
17990template<typename FloatType>
17992void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17993{
17994 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17995 "internal error: not enough precision");
17996
17997 JSON_ASSERT(std::isfinite(value));
17998 JSON_ASSERT(value > 0);
17999
18000 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18001 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18002 // decimal representations are not exactly "short".
18003 //
18004 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18005 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18006 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18007 // does.
18008 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18009 // representation using the corresponding std::from_chars function recovers value exactly". That
18010 // indicates that single precision floating-point numbers should be recovered using
18011 // 'std::strtof'.
18012 //
18013 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18014 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18015 // value is off by 1 ulp.
18016#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18017 const boundaries w = compute_boundaries(static_cast<double>(value));
18018#else
18019 const boundaries w = compute_boundaries(value);
18020#endif
18021
18022 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18023}
18024
18032inline char* append_exponent(char* buf, int e)
18033{
18034 JSON_ASSERT(e > -1000);
18035 JSON_ASSERT(e < 1000);
18036
18037 if (e < 0)
18038 {
18039 e = -e;
18040 *buf++ = '-';
18041 }
18042 else
18043 {
18044 *buf++ = '+';
18045 }
18046
18047 auto k = static_cast<std::uint32_t>(e);
18048 if (k < 10)
18049 {
18050 // Always print at least two digits in the exponent.
18051 // This is for compatibility with printf("%g").
18052 *buf++ = '0';
18053 *buf++ = static_cast<char>('0' + k);
18054 }
18055 else if (k < 100)
18056 {
18057 *buf++ = static_cast<char>('0' + (k / 10));
18058 k %= 10;
18059 *buf++ = static_cast<char>('0' + k);
18060 }
18061 else
18062 {
18063 *buf++ = static_cast<char>('0' + (k / 100));
18064 k %= 100;
18065 *buf++ = static_cast<char>('0' + (k / 10));
18066 k %= 10;
18067 *buf++ = static_cast<char>('0' + k);
18068 }
18069
18070 return buf;
18071}
18072
18084inline char* format_buffer(char* buf, int len, int decimal_exponent,
18085 int min_exp, int max_exp)
18086{
18087 JSON_ASSERT(min_exp < 0);
18088 JSON_ASSERT(max_exp > 0);
18089
18090 const int k = len;
18091 const int n = len + decimal_exponent;
18092
18093 // v = buf * 10^(n-k)
18094 // k is the length of the buffer (number of decimal digits)
18095 // n is the position of the decimal point relative to the start of the buffer.
18096
18097 if (k <= n && n <= max_exp)
18098 {
18099 // digits[000]
18100 // len <= max_exp + 2
18101
18102 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18103 // Make it look like a floating-point number (#362, #378)
18104 buf[n + 0] = '.';
18105 buf[n + 1] = '0';
18106 return buf + (static_cast<size_t>(n) + 2);
18107 }
18108
18109 if (0 < n && n <= max_exp)
18110 {
18111 // dig.its
18112 // len <= max_digits10 + 1
18113
18114 JSON_ASSERT(k > n);
18115
18116 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18117 buf[n] = '.';
18118 return buf + (static_cast<size_t>(k) + 1U);
18119 }
18120
18121 if (min_exp < n && n <= 0)
18122 {
18123 // 0.[000]digits
18124 // len <= 2 + (-min_exp - 1) + max_digits10
18125
18126 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18127 buf[0] = '0';
18128 buf[1] = '.';
18129 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18130 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18131 }
18132
18133 if (k == 1)
18134 {
18135 // dE+123
18136 // len <= 1 + 5
18137
18138 buf += 1;
18139 }
18140 else
18141 {
18142 // d.igitsE+123
18143 // len <= max_digits10 + 1 + 5
18144
18145 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18146 buf[1] = '.';
18147 buf += 1 + static_cast<size_t>(k);
18148 }
18149
18150 *buf++ = 'e';
18151 return append_exponent(buf, n - 1);
18152}
18153
18154} // namespace dtoa_impl
18155
18166template<typename FloatType>
18169char* to_chars(char* first, const char* last, FloatType value)
18170{
18171 static_cast<void>(last); // maybe unused - fix warning
18172 JSON_ASSERT(std::isfinite(value));
18173
18174 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18175 if (std::signbit(value))
18176 {
18177 value = -value;
18178 *first++ = '-';
18179 }
18180
18181#ifdef __GNUC__
18182#pragma GCC diagnostic push
18183#pragma GCC diagnostic ignored "-Wfloat-equal"
18184#endif
18185 if (value == 0) // +-0
18186 {
18187 *first++ = '0';
18188 // Make it look like a floating-point number (#362, #378)
18189 *first++ = '.';
18190 *first++ = '0';
18191 return first;
18192 }
18193#ifdef __GNUC__
18194#pragma GCC diagnostic pop
18195#endif
18196
18197 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18198
18199 // Compute v = buffer * 10^decimal_exponent.
18200 // The decimal digits are stored in the buffer, which needs to be interpreted
18201 // as an unsigned decimal integer.
18202 // len is the length of the buffer, i.e. the number of decimal digits.
18203 int len = 0;
18204 int decimal_exponent = 0;
18205 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18206
18207 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18208
18209 // Format the buffer like printf("%.*g", prec, value)
18210 constexpr int kMinExp = -4;
18211 // Use digits10 here to increase compatibility with version 2.
18212 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18213
18214 JSON_ASSERT(last - first >= kMaxExp + 2);
18215 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18216 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18217
18218 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18219}
18220
18221} // namespace detail
18223
18224// #include <nlohmann/detail/exceptions.hpp>
18225
18226// #include <nlohmann/detail/macro_scope.hpp>
18227
18228// #include <nlohmann/detail/meta/cpp_future.hpp>
18229
18230// #include <nlohmann/detail/output/binary_writer.hpp>
18231
18232// #include <nlohmann/detail/output/output_adapters.hpp>
18233
18234// #include <nlohmann/detail/string_concat.hpp>
18235
18236// #include <nlohmann/detail/value_t.hpp>
18237
18238
18240namespace detail
18241{
18242
18244// serialization //
18246
18249{
18250 strict,
18251 replace,
18252 ignore
18253};
18254
18255template<typename BasicJsonType>
18257{
18258 using string_t = typename BasicJsonType::string_t;
18259 using number_float_t = typename BasicJsonType::number_float_t;
18260 using number_integer_t = typename BasicJsonType::number_integer_t;
18261 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18262 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18263 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18264 static constexpr std::uint8_t UTF8_REJECT = 1;
18265
18266 public:
18272 serializer(output_adapter_t<char> s, const char ichar,
18274 : o(std::move(s))
18275 , loc(std::localeconv())
18276 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18277 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18278 , indent_char(ichar)
18280 , error_handler(error_handler_)
18281 {}
18282
18283 // delete because of pointer members
18284 serializer(const serializer&) = delete;
18288 ~serializer() = default;
18289
18312 void dump(const BasicJsonType& val,
18313 const bool pretty_print,
18314 const bool ensure_ascii,
18315 const unsigned int indent_step,
18316 const unsigned int current_indent = 0)
18317 {
18318 switch (val.m_data.m_type)
18319 {
18320 case value_t::object:
18321 {
18322 if (val.m_data.m_value.object->empty())
18323 {
18324 o->write_characters("{}", 2);
18325 return;
18326 }
18327
18328 if (pretty_print)
18329 {
18330 o->write_characters("{\n", 2);
18331
18332 // variable to hold indentation for recursive calls
18333 const auto new_indent = current_indent + indent_step;
18334 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18335 {
18336 indent_string.resize(indent_string.size() * 2, ' ');
18337 }
18338
18339 // first n-1 elements
18340 auto i = val.m_data.m_value.object->cbegin();
18341 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18342 {
18343 o->write_characters(indent_string.c_str(), new_indent);
18344 o->write_character('\"');
18345 dump_escaped(i->first, ensure_ascii);
18346 o->write_characters("\": ", 3);
18347 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18348 o->write_characters(",\n", 2);
18349 }
18350
18351 // last element
18352 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18353 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18354 o->write_characters(indent_string.c_str(), new_indent);
18355 o->write_character('\"');
18356 dump_escaped(i->first, ensure_ascii);
18357 o->write_characters("\": ", 3);
18358 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18359
18360 o->write_character('\n');
18361 o->write_characters(indent_string.c_str(), current_indent);
18362 o->write_character('}');
18363 }
18364 else
18365 {
18366 o->write_character('{');
18367
18368 // first n-1 elements
18369 auto i = val.m_data.m_value.object->cbegin();
18370 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18371 {
18372 o->write_character('\"');
18373 dump_escaped(i->first, ensure_ascii);
18374 o->write_characters("\":", 2);
18375 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18376 o->write_character(',');
18377 }
18378
18379 // last element
18380 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18381 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18382 o->write_character('\"');
18383 dump_escaped(i->first, ensure_ascii);
18384 o->write_characters("\":", 2);
18385 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18386
18387 o->write_character('}');
18388 }
18389
18390 return;
18391 }
18392
18393 case value_t::array:
18394 {
18395 if (val.m_data.m_value.array->empty())
18396 {
18397 o->write_characters("[]", 2);
18398 return;
18399 }
18400
18401 if (pretty_print)
18402 {
18403 o->write_characters("[\n", 2);
18404
18405 // variable to hold indentation for recursive calls
18406 const auto new_indent = current_indent + indent_step;
18407 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18408 {
18409 indent_string.resize(indent_string.size() * 2, ' ');
18410 }
18411
18412 // first n-1 elements
18413 for (auto i = val.m_data.m_value.array->cbegin();
18414 i != val.m_data.m_value.array->cend() - 1; ++i)
18415 {
18416 o->write_characters(indent_string.c_str(), new_indent);
18417 dump(*i, true, ensure_ascii, indent_step, new_indent);
18418 o->write_characters(",\n", 2);
18419 }
18420
18421 // last element
18422 JSON_ASSERT(!val.m_data.m_value.array->empty());
18423 o->write_characters(indent_string.c_str(), new_indent);
18424 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18425
18426 o->write_character('\n');
18427 o->write_characters(indent_string.c_str(), current_indent);
18428 o->write_character(']');
18429 }
18430 else
18431 {
18432 o->write_character('[');
18433
18434 // first n-1 elements
18435 for (auto i = val.m_data.m_value.array->cbegin();
18436 i != val.m_data.m_value.array->cend() - 1; ++i)
18437 {
18438 dump(*i, false, ensure_ascii, indent_step, current_indent);
18439 o->write_character(',');
18440 }
18441
18442 // last element
18443 JSON_ASSERT(!val.m_data.m_value.array->empty());
18444 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18445
18446 o->write_character(']');
18447 }
18448
18449 return;
18450 }
18451
18452 case value_t::string:
18453 {
18454 o->write_character('\"');
18455 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18456 o->write_character('\"');
18457 return;
18458 }
18459
18460 case value_t::binary:
18461 {
18462 if (pretty_print)
18463 {
18464 o->write_characters("{\n", 2);
18465
18466 // variable to hold indentation for recursive calls
18467 const auto new_indent = current_indent + indent_step;
18468 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18469 {
18470 indent_string.resize(indent_string.size() * 2, ' ');
18471 }
18472
18473 o->write_characters(indent_string.c_str(), new_indent);
18474
18475 o->write_characters("\"bytes\": [", 10);
18476
18477 if (!val.m_data.m_value.binary->empty())
18478 {
18479 for (auto i = val.m_data.m_value.binary->cbegin();
18480 i != val.m_data.m_value.binary->cend() - 1; ++i)
18481 {
18482 dump_integer(*i);
18483 o->write_characters(", ", 2);
18484 }
18485 dump_integer(val.m_data.m_value.binary->back());
18486 }
18487
18488 o->write_characters("],\n", 3);
18489 o->write_characters(indent_string.c_str(), new_indent);
18490
18491 o->write_characters("\"subtype\": ", 11);
18492 if (val.m_data.m_value.binary->has_subtype())
18493 {
18494 dump_integer(val.m_data.m_value.binary->subtype());
18495 }
18496 else
18497 {
18498 o->write_characters("null", 4);
18499 }
18500 o->write_character('\n');
18501 o->write_characters(indent_string.c_str(), current_indent);
18502 o->write_character('}');
18503 }
18504 else
18505 {
18506 o->write_characters("{\"bytes\":[", 10);
18507
18508 if (!val.m_data.m_value.binary->empty())
18509 {
18510 for (auto i = val.m_data.m_value.binary->cbegin();
18511 i != val.m_data.m_value.binary->cend() - 1; ++i)
18512 {
18513 dump_integer(*i);
18514 o->write_character(',');
18515 }
18516 dump_integer(val.m_data.m_value.binary->back());
18517 }
18518
18519 o->write_characters("],\"subtype\":", 12);
18520 if (val.m_data.m_value.binary->has_subtype())
18521 {
18522 dump_integer(val.m_data.m_value.binary->subtype());
18523 o->write_character('}');
18524 }
18525 else
18526 {
18527 o->write_characters("null}", 5);
18528 }
18529 }
18530 return;
18531 }
18532
18533 case value_t::boolean:
18534 {
18535 if (val.m_data.m_value.boolean)
18536 {
18537 o->write_characters("true", 4);
18538 }
18539 else
18540 {
18541 o->write_characters("false", 5);
18542 }
18543 return;
18544 }
18545
18547 {
18548 dump_integer(val.m_data.m_value.number_integer);
18549 return;
18550 }
18551
18553 {
18554 dump_integer(val.m_data.m_value.number_unsigned);
18555 return;
18556 }
18557
18559 {
18560 dump_float(val.m_data.m_value.number_float);
18561 return;
18562 }
18563
18564 case value_t::discarded:
18565 {
18566 o->write_characters("<discarded>", 11);
18567 return;
18568 }
18569
18570 case value_t::null:
18571 {
18572 o->write_characters("null", 4);
18573 return;
18574 }
18575
18576 default: // LCOV_EXCL_LINE
18577 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18578 }
18579 }
18580
18596 void dump_escaped(const string_t& s, const bool ensure_ascii)
18597 {
18598 std::uint32_t codepoint{};
18599 std::uint8_t state = UTF8_ACCEPT;
18600 std::size_t bytes = 0; // number of bytes written to string_buffer
18601
18602 // number of bytes written at the point of the last valid byte
18604 std::size_t undumped_chars = 0;
18605
18606 for (std::size_t i = 0; i < s.size(); ++i)
18607 {
18608 const auto byte = static_cast<std::uint8_t>(s[i]);
18609
18610 switch (decode(state, codepoint, byte))
18611 {
18612 case UTF8_ACCEPT: // decode found a new code point
18613 {
18614 switch (codepoint)
18615 {
18616 case 0x08: // backspace
18617 {
18618 string_buffer[bytes++] = '\\';
18619 string_buffer[bytes++] = 'b';
18620 break;
18621 }
18622
18623 case 0x09: // horizontal tab
18624 {
18625 string_buffer[bytes++] = '\\';
18626 string_buffer[bytes++] = 't';
18627 break;
18628 }
18629
18630 case 0x0A: // newline
18631 {
18632 string_buffer[bytes++] = '\\';
18633 string_buffer[bytes++] = 'n';
18634 break;
18635 }
18636
18637 case 0x0C: // formfeed
18638 {
18639 string_buffer[bytes++] = '\\';
18640 string_buffer[bytes++] = 'f';
18641 break;
18642 }
18643
18644 case 0x0D: // carriage return
18645 {
18646 string_buffer[bytes++] = '\\';
18647 string_buffer[bytes++] = 'r';
18648 break;
18649 }
18650
18651 case 0x22: // quotation mark
18652 {
18653 string_buffer[bytes++] = '\\';
18654 string_buffer[bytes++] = '\"';
18655 break;
18656 }
18657
18658 case 0x5C: // reverse solidus
18659 {
18660 string_buffer[bytes++] = '\\';
18661 string_buffer[bytes++] = '\\';
18662 break;
18663 }
18664
18665 default:
18666 {
18667 // escape control characters (0x00..0x1F) or, if
18668 // ensure_ascii parameter is used, non-ASCII characters
18669 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18670 {
18671 if (codepoint <= 0xFFFF)
18672 {
18673 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18674 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18675 static_cast<std::uint16_t>(codepoint)));
18676 bytes += 6;
18677 }
18678 else
18679 {
18680 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18681 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18682 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18683 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18684 bytes += 12;
18685 }
18686 }
18687 else
18688 {
18689 // copy byte to buffer (all previous bytes
18690 // been copied have in default case above)
18691 string_buffer[bytes++] = s[i];
18692 }
18693 break;
18694 }
18695 }
18696
18697 // write buffer and reset index; there must be 13 bytes
18698 // left, as this is the maximal number of bytes to be
18699 // written ("\uxxxx\uxxxx\0") for one code point
18700 if (string_buffer.size() - bytes < 13)
18701 {
18702 o->write_characters(string_buffer.data(), bytes);
18703 bytes = 0;
18704 }
18705
18706 // remember the byte position of this accept
18708 undumped_chars = 0;
18709 break;
18710 }
18711
18712 case UTF8_REJECT: // decode found invalid UTF-8 byte
18713 {
18714 switch (error_handler)
18715 {
18717 {
18718 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18719 }
18720
18723 {
18724 // in case we saw this character the first time, we
18725 // would like to read it again, because the byte
18726 // may be OK for itself, but just not OK for the
18727 // previous sequence
18728 if (undumped_chars > 0)
18729 {
18730 --i;
18731 }
18732
18733 // reset length buffer to the last accepted index;
18734 // thus removing/ignoring the invalid characters
18736
18738 {
18739 // add a replacement character
18740 if (ensure_ascii)
18741 {
18742 string_buffer[bytes++] = '\\';
18743 string_buffer[bytes++] = 'u';
18744 string_buffer[bytes++] = 'f';
18745 string_buffer[bytes++] = 'f';
18746 string_buffer[bytes++] = 'f';
18747 string_buffer[bytes++] = 'd';
18748 }
18749 else
18750 {
18751 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18752 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18753 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18754 }
18755
18756 // write buffer and reset index; there must be 13 bytes
18757 // left, as this is the maximal number of bytes to be
18758 // written ("\uxxxx\uxxxx\0") for one code point
18759 if (string_buffer.size() - bytes < 13)
18760 {
18761 o->write_characters(string_buffer.data(), bytes);
18762 bytes = 0;
18763 }
18764
18766 }
18767
18768 undumped_chars = 0;
18769
18770 // continue processing the string
18771 state = UTF8_ACCEPT;
18772 break;
18773 }
18774
18775 default: // LCOV_EXCL_LINE
18776 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18777 }
18778 break;
18779 }
18780
18781 default: // decode found yet incomplete multi-byte code point
18782 {
18783 if (!ensure_ascii)
18784 {
18785 // code point will not be escaped - copy byte to buffer
18786 string_buffer[bytes++] = s[i];
18787 }
18789 break;
18790 }
18791 }
18792 }
18793
18794 // we finished processing the string
18795 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18796 {
18797 // write buffer
18798 if (bytes > 0)
18799 {
18800 o->write_characters(string_buffer.data(), bytes);
18801 }
18802 }
18803 else
18804 {
18805 // we finish reading, but do not accept: string was incomplete
18806 switch (error_handler)
18807 {
18809 {
18810 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
18811 }
18812
18814 {
18815 // write all accepted bytes
18816 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18817 break;
18818 }
18819
18821 {
18822 // write all accepted bytes
18823 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18824 // add a replacement character
18825 if (ensure_ascii)
18826 {
18827 o->write_characters("\\ufffd", 6);
18828 }
18829 else
18830 {
18831 o->write_characters("\xEF\xBF\xBD", 3);
18832 }
18833 break;
18834 }
18835
18836 default: // LCOV_EXCL_LINE
18837 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18838 }
18839 }
18840 }
18841
18842 private:
18851 unsigned int count_digits(number_unsigned_t x) noexcept
18852 {
18853 unsigned int n_digits = 1;
18854 for (;;)
18855 {
18856 if (x < 10)
18857 {
18858 return n_digits;
18859 }
18860 if (x < 100)
18861 {
18862 return n_digits + 1;
18863 }
18864 if (x < 1000)
18865 {
18866 return n_digits + 2;
18867 }
18868 if (x < 10000)
18869 {
18870 return n_digits + 3;
18871 }
18872 x = x / 10000u;
18873 n_digits += 4;
18874 }
18875 }
18876
18882 static std::string hex_bytes(std::uint8_t byte)
18883 {
18884 std::string result = "FF";
18885 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18886 result[0] = nibble_to_hex[byte / 16];
18887 result[1] = nibble_to_hex[byte % 16];
18888 return result;
18889 }
18890
18891 // templates to avoid warnings about useless casts
18892 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18893 bool is_negative_number(NumberType x)
18894 {
18895 return x < 0;
18896 }
18897
18898 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18899 bool is_negative_number(NumberType /*unused*/)
18900 {
18901 return false;
18902 }
18903
18913 template < typename NumberType, detail::enable_if_t <
18914 std::is_integral<NumberType>::value ||
18915 std::is_same<NumberType, number_unsigned_t>::value ||
18916 std::is_same<NumberType, number_integer_t>::value ||
18917 std::is_same<NumberType, binary_char_t>::value,
18918 int > = 0 >
18919 void dump_integer(NumberType x)
18920 {
18921 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18922 {
18923 {
18924 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18925 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18926 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18927 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18928 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18929 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18930 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18931 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18932 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18933 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18934 }
18935 };
18936
18937 // special case for "0"
18938 if (x == 0)
18939 {
18940 o->write_character('0');
18941 return;
18942 }
18943
18944 // use a pointer to fill the buffer
18945 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18946
18947 number_unsigned_t abs_value;
18948
18949 unsigned int n_chars{};
18950
18951 if (is_negative_number(x))
18952 {
18953 *buffer_ptr = '-';
18954 abs_value = remove_sign(static_cast<number_integer_t>(x));
18955
18956 // account one more byte for the minus sign
18957 n_chars = 1 + count_digits(abs_value);
18958 }
18959 else
18960 {
18961 abs_value = static_cast<number_unsigned_t>(x);
18962 n_chars = count_digits(abs_value);
18963 }
18964
18965 // spare 1 byte for '\0'
18966 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18967
18968 // jump to the end to generate the string from backward,
18969 // so we later avoid reversing the result
18970 buffer_ptr += n_chars;
18971
18972 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18973 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18974 while (abs_value >= 100)
18975 {
18976 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18977 abs_value /= 100;
18978 *(--buffer_ptr) = digits_to_99[digits_index][1];
18979 *(--buffer_ptr) = digits_to_99[digits_index][0];
18980 }
18981
18982 if (abs_value >= 10)
18983 {
18984 const auto digits_index = static_cast<unsigned>(abs_value);
18985 *(--buffer_ptr) = digits_to_99[digits_index][1];
18986 *(--buffer_ptr) = digits_to_99[digits_index][0];
18987 }
18988 else
18989 {
18990 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18991 }
18992
18993 o->write_characters(number_buffer.data(), n_chars);
18994 }
18995
19004 void dump_float(number_float_t x)
19005 {
19006 // NaN / inf
19007 if (!std::isfinite(x))
19008 {
19009 o->write_characters("null", 4);
19010 return;
19011 }
19012
19013 // If number_float_t is an IEEE-754 single or double precision number,
19014 // use the Grisu2 algorithm to produce short numbers which are
19015 // guaranteed to round-trip, using strtof and strtod, resp.
19016 //
19017 // NB: The test below works if <long double> == <double>.
19018 static constexpr bool is_ieee_single_or_double
19019 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
19020 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
19021
19022 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19023 }
19024
19025 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19026 {
19027 auto* begin = number_buffer.data();
19028 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19029
19030 o->write_characters(begin, static_cast<size_t>(end - begin));
19031 }
19032
19033 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19034 {
19035 // get number of digits for a float -> text -> float round-trip
19036 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19037
19038 // the actual conversion
19039 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19040 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19041
19042 // negative value indicates an error
19043 JSON_ASSERT(len > 0);
19044 // check if buffer was large enough
19045 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19046
19047 // erase thousands separator
19048 if (thousands_sep != '\0')
19049 {
19050 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19051 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19052 std::fill(end, number_buffer.end(), '\0');
19053 JSON_ASSERT((end - number_buffer.begin()) <= len);
19054 len = (end - number_buffer.begin());
19055 }
19056
19057 // convert decimal point to '.'
19058 if (decimal_point != '\0' && decimal_point != '.')
19059 {
19060 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19061 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19062 if (dec_pos != number_buffer.end())
19063 {
19064 *dec_pos = '.';
19065 }
19066 }
19067
19068 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19069
19070 // determine if we need to append ".0"
19071 const bool value_is_int_like =
19072 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19073 [](char c)
19074 {
19075 return c == '.' || c == 'e';
19076 });
19077
19078 if (value_is_int_like)
19079 {
19080 o->write_characters(".0", 2);
19081 }
19082 }
19083
19105 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19106 {
19107 static const std::array<std::uint8_t, 400> utf8d =
19108 {
19109 {
19110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
19111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
19112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
19113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
19114 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
19115 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
19116 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
19117 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19118 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19119 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19120 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
19121 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
19122 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
19123 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
19124 }
19125 };
19126
19127 JSON_ASSERT(byte < utf8d.size());
19128 const std::uint8_t type = utf8d[byte];
19129
19130 codep = (state != UTF8_ACCEPT)
19131 ? (byte & 0x3fu) | (codep << 6u)
19132 : (0xFFu >> type) & (byte);
19133
19134 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19135 JSON_ASSERT(index < utf8d.size());
19136 state = utf8d[index];
19137 return state;
19138 }
19139
19140 /*
19141 * Overload to make the compiler happy while it is instantiating
19142 * dump_integer for number_unsigned_t.
19143 * Must never be called.
19144 */
19145 number_unsigned_t remove_sign(number_unsigned_t x)
19146 {
19147 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19148 return x; // LCOV_EXCL_LINE
19149 }
19150
19151 /*
19152 * Helper function for dump_integer
19153 *
19154 * This function takes a negative signed integer and returns its absolute
19155 * value as unsigned integer. The plus/minus shuffling is necessary as we can
19156 * not directly remove the sign of an arbitrary signed integer as the
19157 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19158 * #1708 for details.
19159 */
19160 number_unsigned_t remove_sign(number_integer_t x) noexcept
19161 {
19162 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19163 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19164 }
19165
19166 private:
19168 output_adapter_t<char> o = nullptr;
19169
19171 std::array<char, 64> number_buffer{{}};
19172
19174 const std::lconv* loc = nullptr;
19176 const char thousands_sep = '\0';
19178 const char decimal_point = '\0';
19179
19181 std::array<char, 512> string_buffer{{}};
19182
19184 const char indent_char;
19187
19190};
19191
19192} // namespace detail
19194
19195// #include <nlohmann/detail/value_t.hpp>
19196
19197// #include <nlohmann/json_fwd.hpp>
19198
19199// #include <nlohmann/ordered_map.hpp>
19200// __ _____ _____ _____
19201// __| | __| | | | JSON for Modern C++
19202// | | |__ | | | | | | version 3.11.3
19203// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19204//
19205// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
19206// SPDX-License-Identifier: MIT
19207
19208
19209
19210#include <functional> // equal_to, less
19211#include <initializer_list> // initializer_list
19212#include <iterator> // input_iterator_tag, iterator_traits
19213#include <memory> // allocator
19214#include <stdexcept> // for out_of_range
19215#include <type_traits> // enable_if, is_convertible
19216#include <utility> // pair
19217#include <vector> // vector
19218
19219// #include <nlohmann/detail/macro_scope.hpp>
19220
19221// #include <nlohmann/detail/meta/type_traits.hpp>
19222
19223
19225
19228template <class Key, class T, class IgnoredLess = std::less<Key>,
19229 class Allocator = std::allocator<std::pair<const Key, T>>>
19230 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19231{
19232 using key_type = Key;
19233 using mapped_type = T;
19234 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19235 using iterator = typename Container::iterator;
19236 using const_iterator = typename Container::const_iterator;
19237 using size_type = typename Container::size_type;
19238 using value_type = typename Container::value_type;
19239#ifdef JSON_HAS_CPP_14
19240 using key_compare = std::equal_to<>;
19241#else
19242 using key_compare = std::equal_to<Key>;
19243#endif
19244
19245 // Explicit constructors instead of `using Container::Container`
19246 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19247 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19248 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19249 template <class It>
19250 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19251 : Container{first, last, alloc} {}
19252 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19253 : Container{init, alloc} {}
19254
19255 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19256 {
19257 for (auto it = this->begin(); it != this->end(); ++it)
19258 {
19259 if (m_compare(it->first, key))
19260 {
19261 return {it, false};
19262 }
19263 }
19264 Container::emplace_back(key, std::forward<T>(t));
19265 return {std::prev(this->end()), true};
19266 }
19267
19268 template<class KeyType, detail::enable_if_t<
19270 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19271 {
19272 for (auto it = this->begin(); it != this->end(); ++it)
19273 {
19274 if (m_compare(it->first, key))
19275 {
19276 return {it, false};
19277 }
19278 }
19279 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19280 return {std::prev(this->end()), true};
19281 }
19282
19283 T& operator[](const key_type& key)
19284 {
19285 return emplace(key, T{}).first->second;
19286 }
19287
19288 template<class KeyType, detail::enable_if_t<
19290 T & operator[](KeyType && key)
19291 {
19292 return emplace(std::forward<KeyType>(key), T{}).first->second;
19293 }
19294
19295 const T& operator[](const key_type& key) const
19296 {
19297 return at(key);
19298 }
19299
19300 template<class KeyType, detail::enable_if_t<
19302 const T & operator[](KeyType && key) const
19303 {
19304 return at(std::forward<KeyType>(key));
19305 }
19306
19307 T& at(const key_type& key)
19308 {
19309 for (auto it = this->begin(); it != this->end(); ++it)
19310 {
19311 if (m_compare(it->first, key))
19312 {
19313 return it->second;
19314 }
19315 }
19316
19317 JSON_THROW(std::out_of_range("key not found"));
19318 }
19319
19320 template<class KeyType, detail::enable_if_t<
19322 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19323 {
19324 for (auto it = this->begin(); it != this->end(); ++it)
19325 {
19326 if (m_compare(it->first, key))
19327 {
19328 return it->second;
19329 }
19330 }
19331
19332 JSON_THROW(std::out_of_range("key not found"));
19333 }
19334
19335 const T& at(const key_type& key) const
19336 {
19337 for (auto it = this->begin(); it != this->end(); ++it)
19338 {
19339 if (m_compare(it->first, key))
19340 {
19341 return it->second;
19342 }
19343 }
19344
19345 JSON_THROW(std::out_of_range("key not found"));
19346 }
19347
19348 template<class KeyType, detail::enable_if_t<
19350 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19351 {
19352 for (auto it = this->begin(); it != this->end(); ++it)
19353 {
19354 if (m_compare(it->first, key))
19355 {
19356 return it->second;
19357 }
19358 }
19359
19360 JSON_THROW(std::out_of_range("key not found"));
19361 }
19362
19364 {
19365 for (auto it = this->begin(); it != this->end(); ++it)
19366 {
19367 if (m_compare(it->first, key))
19368 {
19369 // Since we cannot move const Keys, re-construct them in place
19370 for (auto next = it; ++next != this->end(); ++it)
19371 {
19372 it->~value_type(); // Destroy but keep allocation
19373 new (&*it) value_type{std::move(*next)};
19374 }
19375 Container::pop_back();
19376 return 1;
19377 }
19378 }
19379 return 0;
19380 }
19381
19382 template<class KeyType, detail::enable_if_t<
19384 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19385 {
19386 for (auto it = this->begin(); it != this->end(); ++it)
19387 {
19388 if (m_compare(it->first, key))
19389 {
19390 // Since we cannot move const Keys, re-construct them in place
19391 for (auto next = it; ++next != this->end(); ++it)
19392 {
19393 it->~value_type(); // Destroy but keep allocation
19394 new (&*it) value_type{std::move(*next)};
19395 }
19396 Container::pop_back();
19397 return 1;
19398 }
19399 }
19400 return 0;
19401 }
19402
19404 {
19405 return erase(pos, std::next(pos));
19406 }
19407
19409 {
19410 if (first == last)
19411 {
19412 return first;
19413 }
19414
19415 const auto elements_affected = std::distance(first, last);
19416 const auto offset = std::distance(Container::begin(), first);
19417
19418 // This is the start situation. We need to delete elements_affected
19419 // elements (3 in this example: e, f, g), and need to return an
19420 // iterator past the last deleted element (h in this example).
19421 // Note that offset is the distance from the start of the vector
19422 // to first. We will need this later.
19423
19424 // [ a, b, c, d, e, f, g, h, i, j ]
19425 // ^ ^
19426 // first last
19427
19428 // Since we cannot move const Keys, we re-construct them in place.
19429 // We start at first and re-construct (viz. copy) the elements from
19430 // the back of the vector. Example for first iteration:
19431
19432 // ,--------.
19433 // v | destroy e and re-construct with h
19434 // [ a, b, c, d, e, f, g, h, i, j ]
19435 // ^ ^
19436 // it it + elements_affected
19437
19438 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19439 {
19440 it->~value_type(); // destroy but keep allocation
19441 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19442 }
19443
19444 // [ a, b, c, d, h, i, j, h, i, j ]
19445 // ^ ^
19446 // first last
19447
19448 // remove the unneeded elements at the end of the vector
19449 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19450
19451 // [ a, b, c, d, h, i, j ]
19452 // ^ ^
19453 // first last
19454
19455 // first is now pointing past the last deleted element, but we cannot
19456 // use this iterator, because it may have been invalidated by the
19457 // resize call. Instead, we can return begin() + offset.
19458 return Container::begin() + offset;
19459 }
19460
19461 size_type count(const key_type& key) const
19462 {
19463 for (auto it = this->begin(); it != this->end(); ++it)
19464 {
19465 if (m_compare(it->first, key))
19466 {
19467 return 1;
19468 }
19469 }
19470 return 0;
19471 }
19472
19473 template<class KeyType, detail::enable_if_t<
19475 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19476 {
19477 for (auto it = this->begin(); it != this->end(); ++it)
19478 {
19479 if (m_compare(it->first, key))
19480 {
19481 return 1;
19482 }
19483 }
19484 return 0;
19485 }
19486
19488 {
19489 for (auto it = this->begin(); it != this->end(); ++it)
19490 {
19491 if (m_compare(it->first, key))
19492 {
19493 return it;
19494 }
19495 }
19496 return Container::end();
19497 }
19498
19499 template<class KeyType, detail::enable_if_t<
19501 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19502 {
19503 for (auto it = this->begin(); it != this->end(); ++it)
19504 {
19505 if (m_compare(it->first, key))
19506 {
19507 return it;
19508 }
19509 }
19510 return Container::end();
19511 }
19512
19513 const_iterator find(const key_type& key) const
19514 {
19515 for (auto it = this->begin(); it != this->end(); ++it)
19516 {
19517 if (m_compare(it->first, key))
19518 {
19519 return it;
19520 }
19521 }
19522 return Container::end();
19523 }
19524
19525 std::pair<iterator, bool> insert( value_type&& value )
19526 {
19527 return emplace(value.first, std::move(value.second));
19528 }
19529
19530 std::pair<iterator, bool> insert( const value_type& value )
19531 {
19532 for (auto it = this->begin(); it != this->end(); ++it)
19533 {
19534 if (m_compare(it->first, value.first))
19535 {
19536 return {it, false};
19537 }
19538 }
19539 Container::push_back(value);
19540 return {--this->end(), true};
19541 }
19542
19543 template<typename InputIt>
19544 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19545 std::input_iterator_tag>::value>::type;
19546
19547 template<typename InputIt, typename = require_input_iter<InputIt>>
19548 void insert(InputIt first, InputIt last)
19549 {
19550 for (auto it = first; it != last; ++it)
19551 {
19552 insert(*it);
19553 }
19554 }
19555
19556private:
19558};
19559
19561
19562
19563#if defined(JSON_HAS_CPP_17)
19564 #if JSON_HAS_STATIC_RTTI
19565 #include <any>
19566 #endif
19567 #include <string_view>
19568#endif
19569
19576
19596class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19597 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19598{
19599 private:
19600 template<detail::value_t> friend struct detail::external_constructor;
19601
19602 template<typename>
19603 friend class ::nlohmann::json_pointer;
19604 // can be restored when json_pointer backwards compatibility is removed
19605 // friend ::nlohmann::json_pointer<StringType>;
19606
19607 template<typename BasicJsonType, typename InputType>
19608 friend class ::nlohmann::detail::parser;
19609 friend ::nlohmann::detail::serializer<basic_json>;
19610 template<typename BasicJsonType>
19611 friend class ::nlohmann::detail::iter_impl;
19612 template<typename BasicJsonType, typename CharType>
19613 friend class ::nlohmann::detail::binary_writer;
19614 template<typename BasicJsonType, typename InputType, typename SAX>
19615 friend class ::nlohmann::detail::binary_reader;
19616 template<typename BasicJsonType>
19617 friend class ::nlohmann::detail::json_sax_dom_parser;
19618 template<typename BasicJsonType>
19619 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19620 friend class ::nlohmann::detail::exception;
19621
19623 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19624 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19625
19627 // convenience aliases for types residing in namespace detail;
19628 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19629
19630 template<typename InputAdapterType>
19631 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19632 InputAdapterType adapter,
19633 detail::parser_callback_t<basic_json>cb = nullptr,
19634 const bool allow_exceptions = true,
19635 const bool ignore_comments = false
19636 )
19637 {
19638 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19639 std::move(cb), allow_exceptions, ignore_comments);
19640 }
19641
19642 private:
19643 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19644 template<typename BasicJsonType>
19645 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19646 template<typename BasicJsonType>
19647 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19648 template<typename Iterator>
19649 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19650 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19651
19652 template<typename CharType>
19653 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19654
19655 template<typename InputType>
19656 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19657 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19658
19660 using serializer = ::nlohmann::detail::serializer<basic_json>;
19661
19662 public:
19665 using json_pointer = ::nlohmann::json_pointer<StringType>;
19666 template<typename T, typename SFINAE>
19667 using json_serializer = JSONSerializer<T, SFINAE>;
19673 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19674
19675 using input_format_t = detail::input_format_t;
19678
19680 // exceptions //
19682
19686
19693
19695
19697 // container types //
19699
19704
19707
19712
19714 using difference_type = std::ptrdiff_t;
19716 using size_type = std::size_t;
19717
19719 using allocator_type = AllocatorType<basic_json>;
19720
19722 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19724 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19725
19727 using iterator = iter_impl<basic_json>;
19729 using const_iterator = iter_impl<const basic_json>;
19731 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19733 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19734
19736
19740 {
19741 return allocator_type();
19742 }
19743
19748 {
19749 basic_json result;
19750
19751 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19752 result["name"] = "JSON for Modern C++";
19753 result["url"] = "https://github.com/nlohmann/json";
19754 result["version"]["string"] =
19755 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19756 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19757 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19758 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19759 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19760 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19761
19762#ifdef _WIN32
19763 result["platform"] = "win32";
19764#elif defined __linux__
19765 result["platform"] = "linux";
19766#elif defined __APPLE__
19767 result["platform"] = "apple";
19768#elif defined __unix__
19769 result["platform"] = "unix";
19770#else
19771 result["platform"] = "unknown";
19772#endif
19773
19774#if defined(__ICC) || defined(__INTEL_COMPILER)
19775 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19776#elif defined(__clang__)
19777 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19778#elif defined(__GNUC__) || defined(__GNUG__)
19779 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19780 std::to_string(__GNUC__), '.',
19781 std::to_string(__GNUC_MINOR__), '.',
19782 std::to_string(__GNUC_PATCHLEVEL__))
19783 }
19784 };
19785#elif defined(__HP_cc) || defined(__HP_aCC)
19786 result["compiler"] = "hp"
19787#elif defined(__IBMCPP__)
19788 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19789#elif defined(_MSC_VER)
19790 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19791#elif defined(__PGI)
19792 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19793#elif defined(__SUNPRO_CC)
19794 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19795#else
19796 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19797#endif
19798
19799#if defined(_MSVC_LANG)
19800 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19801#elif defined(__cplusplus)
19802 result["compiler"]["c++"] = std::to_string(__cplusplus);
19803#else
19804 result["compiler"]["c++"] = "unknown";
19805#endif
19806 return result;
19807 }
19808
19810 // JSON value data types //
19812
19817
19822#if defined(JSON_HAS_CPP_14)
19823 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19824 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19825 using default_object_comparator_t = std::less<>;
19826#else
19827 using default_object_comparator_t = std::less<StringType>;
19828#endif
19829
19832 using object_t = ObjectType<StringType,
19833 basic_json,
19835 AllocatorType<std::pair<const StringType,
19836 basic_json>>>;
19837
19840 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19841
19844 using string_t = StringType;
19845
19848 using boolean_t = BooleanType;
19849
19852 using number_integer_t = NumberIntegerType;
19853
19856 using number_unsigned_t = NumberUnsignedType;
19857
19860 using number_float_t = NumberFloatType;
19861
19864 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19865
19869
19871
19872 private:
19873
19875 template<typename T, typename... Args>
19877 static T* create(Args&& ... args)
19878 {
19879 AllocatorType<T> alloc;
19880 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19881
19882 auto deleter = [&](T * obj)
19883 {
19884 AllocatorTraits::deallocate(alloc, obj, 1);
19885 };
19886 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19887 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19888 JSON_ASSERT(obj != nullptr);
19889 return obj.release();
19890 }
19891
19893 // JSON value storage //
19895
19922 union json_value
19923 {
19927 array_t* array;
19931 binary_t* binary;
19933 boolean_t boolean;
19935 number_integer_t number_integer;
19937 number_unsigned_t number_unsigned;
19939 number_float_t number_float;
19940
19942 json_value() = default;
19944 json_value(boolean_t v) noexcept : boolean(v) {}
19946 json_value(number_integer_t v) noexcept : number_integer(v) {}
19948 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19950 json_value(number_float_t v) noexcept : number_float(v) {}
19952 json_value(value_t t)
19953 {
19954 switch (t)
19955 {
19956 case value_t::object:
19957 {
19958 object = create<object_t>();
19959 break;
19960 }
19961
19962 case value_t::array:
19963 {
19964 array = create<array_t>();
19965 break;
19966 }
19967
19968 case value_t::string:
19969 {
19970 string = create<string_t>("");
19971 break;
19972 }
19973
19974 case value_t::binary:
19975 {
19976 binary = create<binary_t>();
19977 break;
19978 }
19979
19980 case value_t::boolean:
19981 {
19982 boolean = static_cast<boolean_t>(false);
19983 break;
19984 }
19985
19986 case value_t::number_integer:
19987 {
19988 number_integer = static_cast<number_integer_t>(0);
19989 break;
19990 }
19991
19992 case value_t::number_unsigned:
19993 {
19994 number_unsigned = static_cast<number_unsigned_t>(0);
19995 break;
19996 }
19997
19998 case value_t::number_float:
19999 {
20000 number_float = static_cast<number_float_t>(0.0);
20001 break;
20002 }
20003
20004 case value_t::null:
20005 {
20006 object = nullptr; // silence warning, see #821
20007 break;
20008 }
20009
20010 case value_t::discarded:
20011 default:
20012 {
20013 object = nullptr; // silence warning, see #821
20014 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20015 {
20016 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
20017 }
20018 break;
20019 }
20020 }
20021 }
20022
20024 json_value(const string_t& value) : string(create<string_t>(value)) {}
20025
20027 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20028
20030 json_value(const object_t& value) : object(create<object_t>(value)) {}
20031
20033 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20034
20036 json_value(const array_t& value) : array(create<array_t>(value)) {}
20037
20039 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20040
20042 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20043
20045 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20046
20048 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20049
20051 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20052
20053 void destroy(value_t t)
20054 {
20055 if (
20056 (t == value_t::object && object == nullptr) ||
20057 (t == value_t::array && array == nullptr) ||
20058 (t == value_t::string && string == nullptr) ||
20059 (t == value_t::binary && binary == nullptr)
20060 )
20061 {
20062 //not initialized (e.g. due to exception in the ctor)
20063 return;
20064 }
20065 if (t == value_t::array || t == value_t::object)
20066 {
20067 // flatten the current json_value to a heap-allocated stack
20068 std::vector<basic_json> stack;
20069
20070 // move the top-level items to stack
20071 if (t == value_t::array)
20072 {
20073 stack.reserve(array->size());
20074 std::move(array->begin(), array->end(), std::back_inserter(stack));
20075 }
20076 else
20077 {
20078 stack.reserve(object->size());
20079 for (auto&& it : *object)
20080 {
20081 stack.push_back(std::move(it.second));
20082 }
20083 }
20084
20085 while (!stack.empty())
20086 {
20087 // move the last item to local variable to be processed
20088 basic_json current_item(std::move(stack.back()));
20089 stack.pop_back();
20090
20091 // if current_item is array/object, move
20092 // its children to the stack to be processed later
20093 if (current_item.is_array())
20094 {
20095 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20096
20097 current_item.m_data.m_value.array->clear();
20098 }
20099 else if (current_item.is_object())
20100 {
20101 for (auto&& it : *current_item.m_data.m_value.object)
20102 {
20103 stack.push_back(std::move(it.second));
20104 }
20105
20106 current_item.m_data.m_value.object->clear();
20107 }
20108
20109 // it's now safe that current_item get destructed
20110 // since it doesn't have any children
20111 }
20112 }
20113
20114 switch (t)
20115 {
20116 case value_t::object:
20117 {
20118 AllocatorType<object_t> alloc;
20119 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20120 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20121 break;
20122 }
20123
20124 case value_t::array:
20125 {
20126 AllocatorType<array_t> alloc;
20127 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20128 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20129 break;
20130 }
20131
20132 case value_t::string:
20133 {
20134 AllocatorType<string_t> alloc;
20135 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20136 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20137 break;
20138 }
20139
20140 case value_t::binary:
20141 {
20142 AllocatorType<binary_t> alloc;
20143 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20144 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20145 break;
20146 }
20147
20148 case value_t::null:
20149 case value_t::boolean:
20150 case value_t::number_integer:
20151 case value_t::number_unsigned:
20152 case value_t::number_float:
20153 case value_t::discarded:
20154 default:
20155 {
20156 break;
20157 }
20158 }
20159 }
20160 };
20161
20162 private:
20181 void assert_invariant(bool check_parents = true) const noexcept
20182 {
20183 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20184 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20185 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20186 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20187
20188#if JSON_DIAGNOSTICS
20189 JSON_TRY
20190 {
20191 // cppcheck-suppress assertWithSideEffect
20192 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20193 {
20194 return j.m_parent == this;
20195 }));
20196 }
20197 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20198#endif
20199 static_cast<void>(check_parents);
20200 }
20201
20202 void set_parents()
20203 {
20204#if JSON_DIAGNOSTICS
20205 switch (m_data.m_type)
20206 {
20207 case value_t::array:
20208 {
20209 for (auto& element : *m_data.m_value.array)
20210 {
20211 element.m_parent = this;
20212 }
20213 break;
20214 }
20215
20216 case value_t::object:
20217 {
20218 for (auto& element : *m_data.m_value.object)
20219 {
20220 element.second.m_parent = this;
20221 }
20222 break;
20223 }
20224
20225 case value_t::null:
20226 case value_t::string:
20227 case value_t::boolean:
20228 case value_t::number_integer:
20229 case value_t::number_unsigned:
20230 case value_t::number_float:
20231 case value_t::binary:
20232 case value_t::discarded:
20233 default:
20234 break;
20235 }
20236#endif
20237 }
20238
20239 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20240 {
20241#if JSON_DIAGNOSTICS
20242 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20243 {
20244 (it + i)->m_parent = this;
20245 }
20246#else
20247 static_cast<void>(count_set_parents);
20248#endif
20249 return it;
20250 }
20251
20252 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20253 {
20254#if JSON_DIAGNOSTICS
20255 if (old_capacity != static_cast<std::size_t>(-1))
20256 {
20257 // see https://github.com/nlohmann/json/issues/2838
20258 JSON_ASSERT(type() == value_t::array);
20259 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20260 {
20261 // capacity has changed: update all parents
20262 set_parents();
20263 return j;
20264 }
20265 }
20266
20267 // ordered_json uses a vector internally, so pointers could have
20268 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20269#ifdef JSON_HEDLEY_MSVC_VERSION
20270#pragma warning(push )
20271#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20272#endif
20274 {
20275 set_parents();
20276 return j;
20277 }
20278#ifdef JSON_HEDLEY_MSVC_VERSION
20279#pragma warning( pop )
20280#endif
20281
20282 j.m_parent = this;
20283#else
20284 static_cast<void>(j);
20285 static_cast<void>(old_capacity);
20286#endif
20287 return j;
20288 }
20289
20290 public:
20292 // JSON parser callback //
20294
20297 using parse_event_t = detail::parse_event_t;
20298
20301 using parser_callback_t = detail::parser_callback_t<basic_json>;
20302
20304 // constructors //
20306
20311
20315 : m_data(v)
20316 {
20317 assert_invariant();
20318 }
20319
20322 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20323 : basic_json(value_t::null)
20324 {
20325 assert_invariant();
20326 }
20327
20330 template < typename CompatibleType,
20334 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20335 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20336 std::forward<CompatibleType>(val))))
20337 {
20338 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20339 set_parents();
20340 assert_invariant();
20341 }
20342
20345 template < typename BasicJsonType,
20347 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20348 basic_json(const BasicJsonType& val)
20349 {
20350 using other_boolean_t = typename BasicJsonType::boolean_t;
20351 using other_number_float_t = typename BasicJsonType::number_float_t;
20352 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20353 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20354 using other_string_t = typename BasicJsonType::string_t;
20355 using other_object_t = typename BasicJsonType::object_t;
20356 using other_array_t = typename BasicJsonType::array_t;
20357 using other_binary_t = typename BasicJsonType::binary_t;
20358
20359 switch (val.type())
20360 {
20361 case value_t::boolean:
20362 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20363 break;
20364 case value_t::number_float:
20365 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20366 break;
20367 case value_t::number_integer:
20368 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20369 break;
20370 case value_t::number_unsigned:
20371 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20372 break;
20373 case value_t::string:
20374 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20375 break;
20376 case value_t::object:
20377 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20378 break;
20379 case value_t::array:
20380 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20381 break;
20382 case value_t::binary:
20383 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20384 break;
20385 case value_t::null:
20386 *this = nullptr;
20387 break;
20388 case value_t::discarded:
20389 m_data.m_type = value_t::discarded;
20390 break;
20391 default: // LCOV_EXCL_LINE
20392 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20393 }
20394 JSON_ASSERT(m_data.m_type == val.type());
20395 set_parents();
20396 assert_invariant();
20397 }
20398
20402 bool type_deduction = true,
20403 value_t manual_type = value_t::array)
20404 {
20405 // check if each element is an array with two elements whose first
20406 // element is a string
20407 bool is_an_object = std::all_of(init.begin(), init.end(),
20408 [](const detail::json_ref<basic_json>& element_ref)
20409 {
20410 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20411 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20412 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20413 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20414 });
20415
20416 // adjust type if type deduction is not wanted
20417 if (!type_deduction)
20418 {
20419 // if array is wanted, do not create an object though possible
20420 if (manual_type == value_t::array)
20421 {
20422 is_an_object = false;
20423 }
20424
20425 // if object is wanted but impossible, throw an exception
20426 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20427 {
20428 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20429 }
20430 }
20431
20432 if (is_an_object)
20433 {
20434 // the initializer list is a list of pairs -> create object
20435 m_data.m_type = value_t::object;
20436 m_data.m_value = value_t::object;
20437
20438 for (auto& element_ref : init)
20439 {
20440 auto element = element_ref.moved_or_copied();
20441 m_data.m_value.object->emplace(
20442 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20443 std::move((*element.m_data.m_value.array)[1]));
20444 }
20445 }
20446 else
20447 {
20448 // the initializer list describes an array -> create array
20449 m_data.m_type = value_t::array;
20450 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20451 }
20452
20453 set_parents();
20454 assert_invariant();
20455 }
20456
20460 static basic_json binary(const typename binary_t::container_type& init)
20461 {
20462 auto res = basic_json();
20463 res.m_data.m_type = value_t::binary;
20464 res.m_data.m_value = init;
20465 return res;
20466 }
20467
20471 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20472 {
20473 auto res = basic_json();
20474 res.m_data.m_type = value_t::binary;
20475 res.m_data.m_value = binary_t(init, subtype);
20476 return res;
20477 }
20478
20482 static basic_json binary(typename binary_t::container_type&& init)
20483 {
20484 auto res = basic_json();
20485 res.m_data.m_type = value_t::binary;
20486 res.m_data.m_value = std::move(init);
20487 return res;
20488 }
20489
20493 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20494 {
20495 auto res = basic_json();
20496 res.m_data.m_type = value_t::binary;
20497 res.m_data.m_value = binary_t(std::move(init), subtype);
20498 return res;
20499 }
20500
20505 {
20506 return basic_json(init, false, value_t::array);
20507 }
20508
20513 {
20514 return basic_json(init, false, value_t::object);
20515 }
20516
20520 m_data{cnt, val}
20521 {
20522 set_parents();
20523 assert_invariant();
20524 }
20525
20528 template < class InputIT, typename std::enable_if <
20529 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20530 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20531 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
20532 {
20533 JSON_ASSERT(first.m_object != nullptr);
20534 JSON_ASSERT(last.m_object != nullptr);
20535
20536 // make sure iterator fits the current value
20537 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20538 {
20539 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20540 }
20541
20542 // copy type from first iterator
20543 m_data.m_type = first.m_object->m_data.m_type;
20544
20545 // check if iterator range is complete for primitive values
20546 switch (m_data.m_type)
20547 {
20548 case value_t::boolean:
20549 case value_t::number_float:
20550 case value_t::number_integer:
20551 case value_t::number_unsigned:
20552 case value_t::string:
20553 {
20554 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20555 || !last.m_it.primitive_iterator.is_end()))
20556 {
20557 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20558 }
20559 break;
20560 }
20561
20562 case value_t::null:
20563 case value_t::object:
20564 case value_t::array:
20565 case value_t::binary:
20566 case value_t::discarded:
20567 default:
20568 break;
20569 }
20570
20571 switch (m_data.m_type)
20572 {
20573 case value_t::number_integer:
20574 {
20575 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20576 break;
20577 }
20578
20579 case value_t::number_unsigned:
20580 {
20581 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20582 break;
20583 }
20584
20585 case value_t::number_float:
20586 {
20587 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20588 break;
20589 }
20590
20591 case value_t::boolean:
20592 {
20593 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20594 break;
20595 }
20596
20597 case value_t::string:
20598 {
20599 m_data.m_value = *first.m_object->m_data.m_value.string;
20600 break;
20601 }
20602
20603 case value_t::object:
20604 {
20605 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20606 last.m_it.object_iterator);
20607 break;
20608 }
20609
20610 case value_t::array:
20611 {
20612 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20613 last.m_it.array_iterator);
20614 break;
20615 }
20616
20617 case value_t::binary:
20618 {
20619 m_data.m_value = *first.m_object->m_data.m_value.binary;
20620 break;
20621 }
20622
20623 case value_t::null:
20624 case value_t::discarded:
20625 default:
20626 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20627 }
20628
20629 set_parents();
20630 assert_invariant();
20631 }
20632
20634 // other constructors and destructor //
20636
20637 template<typename JsonRef,
20639 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20640 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20641
20645 : json_base_class_t(other)
20646 {
20647 m_data.m_type = other.m_data.m_type;
20648 // check of passed value is valid
20649 other.assert_invariant();
20650
20651 switch (m_data.m_type)
20652 {
20653 case value_t::object:
20654 {
20655 m_data.m_value = *other.m_data.m_value.object;
20656 break;
20657 }
20658
20659 case value_t::array:
20660 {
20661 m_data.m_value = *other.m_data.m_value.array;
20662 break;
20663 }
20664
20665 case value_t::string:
20666 {
20667 m_data.m_value = *other.m_data.m_value.string;
20668 break;
20669 }
20670
20671 case value_t::boolean:
20672 {
20673 m_data.m_value = other.m_data.m_value.boolean;
20674 break;
20675 }
20676
20677 case value_t::number_integer:
20678 {
20679 m_data.m_value = other.m_data.m_value.number_integer;
20680 break;
20681 }
20682
20683 case value_t::number_unsigned:
20684 {
20685 m_data.m_value = other.m_data.m_value.number_unsigned;
20686 break;
20687 }
20688
20689 case value_t::number_float:
20690 {
20691 m_data.m_value = other.m_data.m_value.number_float;
20692 break;
20693 }
20694
20695 case value_t::binary:
20696 {
20697 m_data.m_value = *other.m_data.m_value.binary;
20698 break;
20699 }
20700
20701 case value_t::null:
20702 case value_t::discarded:
20703 default:
20704 break;
20705 }
20706
20707 set_parents();
20708 assert_invariant();
20709 }
20710
20713 basic_json(basic_json&& other) noexcept
20714 : json_base_class_t(std::forward<json_base_class_t>(other)),
20715 m_data(std::move(other.m_data))
20716 {
20717 // check that passed value is valid
20718 other.assert_invariant(false);
20719
20720 // invalidate payload
20721 other.m_data.m_type = value_t::null;
20722 other.m_data.m_value = {};
20723
20724 set_parents();
20725 assert_invariant();
20726 }
20727
20731 std::is_nothrow_move_constructible<value_t>::value&&
20732 std::is_nothrow_move_assignable<value_t>::value&&
20733 std::is_nothrow_move_constructible<json_value>::value&&
20734 std::is_nothrow_move_assignable<json_value>::value&&
20735 std::is_nothrow_move_assignable<json_base_class_t>::value
20736 )
20737 {
20738 // check that passed value is valid
20739 other.assert_invariant();
20740
20741 using std::swap;
20742 swap(m_data.m_type, other.m_data.m_type);
20743 swap(m_data.m_value, other.m_data.m_value);
20744 json_base_class_t::operator=(std::move(other));
20745
20746 set_parents();
20747 assert_invariant();
20748 return *this;
20749 }
20750
20753 ~basic_json() noexcept
20754 {
20755 assert_invariant(false);
20756 }
20757
20759
20760 public:
20762 // object inspection //
20764
20768
20771 string_t dump(const int indent = -1,
20772 const char indent_char = ' ',
20773 const bool ensure_ascii = false,
20774 const error_handler_t error_handler = error_handler_t::strict) const
20775 {
20776 string_t result;
20777 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20778
20779 if (indent >= 0)
20780 {
20781 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20782 }
20783 else
20784 {
20785 s.dump(*this, false, ensure_ascii, 0);
20786 }
20787
20788 return result;
20789 }
20790
20793 constexpr value_t type() const noexcept
20794 {
20795 return m_data.m_type;
20796 }
20797
20800 constexpr bool is_primitive() const noexcept
20801 {
20802 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20803 }
20804
20807 constexpr bool is_structured() const noexcept
20808 {
20809 return is_array() || is_object();
20810 }
20811
20814 constexpr bool is_null() const noexcept
20815 {
20816 return m_data.m_type == value_t::null;
20817 }
20818
20821 constexpr bool is_boolean() const noexcept
20822 {
20823 return m_data.m_type == value_t::boolean;
20824 }
20825
20828 constexpr bool is_number() const noexcept
20829 {
20830 return is_number_integer() || is_number_float();
20831 }
20832
20835 constexpr bool is_number_integer() const noexcept
20836 {
20837 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20838 }
20839
20842 constexpr bool is_number_unsigned() const noexcept
20843 {
20844 return m_data.m_type == value_t::number_unsigned;
20845 }
20846
20849 constexpr bool is_number_float() const noexcept
20850 {
20851 return m_data.m_type == value_t::number_float;
20852 }
20853
20856 constexpr bool is_object() const noexcept
20857 {
20858 return m_data.m_type == value_t::object;
20859 }
20860
20863 constexpr bool is_array() const noexcept
20864 {
20865 return m_data.m_type == value_t::array;
20866 }
20867
20870 constexpr bool is_string() const noexcept
20871 {
20872 return m_data.m_type == value_t::string;
20873 }
20874
20877 constexpr bool is_binary() const noexcept
20878 {
20879 return m_data.m_type == value_t::binary;
20880 }
20881
20884 constexpr bool is_discarded() const noexcept
20885 {
20886 return m_data.m_type == value_t::discarded;
20887 }
20888
20891 constexpr operator value_t() const noexcept
20892 {
20893 return m_data.m_type;
20894 }
20895
20897
20898 private:
20900 // value access //
20902
20904 boolean_t get_impl(boolean_t* /*unused*/) const
20905 {
20907 {
20908 return m_data.m_value.boolean;
20909 }
20910
20911 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20912 }
20913
20915 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20916 {
20917 return is_object() ? m_data.m_value.object : nullptr;
20918 }
20919
20921 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20922 {
20923 return is_object() ? m_data.m_value.object : nullptr;
20924 }
20925
20927 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20928 {
20929 return is_array() ? m_data.m_value.array : nullptr;
20930 }
20931
20933 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20934 {
20935 return is_array() ? m_data.m_value.array : nullptr;
20936 }
20937
20939 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20940 {
20941 return is_string() ? m_data.m_value.string : nullptr;
20942 }
20943
20945 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20946 {
20947 return is_string() ? m_data.m_value.string : nullptr;
20948 }
20949
20951 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20952 {
20953 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20954 }
20955
20957 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20958 {
20959 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20960 }
20961
20963 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20964 {
20965 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20966 }
20967
20969 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20970 {
20971 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20972 }
20973
20975 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20976 {
20977 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20978 }
20979
20981 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20982 {
20983 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20984 }
20985
20987 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20988 {
20989 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20990 }
20991
20993 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20994 {
20995 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20996 }
20997
20999 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21000 {
21001 return is_binary() ? m_data.m_value.binary : nullptr;
21002 }
21003
21005 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21006 {
21007 return is_binary() ? m_data.m_value.binary : nullptr;
21008 }
21009
21021 template<typename ReferenceType, typename ThisType>
21022 static ReferenceType get_ref_impl(ThisType& obj)
21023 {
21024 // delegate the call to get_ptr<>()
21025 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21026
21027 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21028 {
21029 return *ptr;
21030 }
21031
21032 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21033 }
21034
21035 public:
21039
21042 template<typename PointerType, typename std::enable_if<
21043 std::is_pointer<PointerType>::value, int>::type = 0>
21044 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21045 {
21046 // delegate the call to get_impl_ptr<>()
21047 return get_impl_ptr(static_cast<PointerType>(nullptr));
21048 }
21049
21052 template < typename PointerType, typename std::enable_if <
21053 std::is_pointer<PointerType>::value&&
21054 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21055 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21056 {
21057 // delegate the call to get_impl_ptr<>() const
21058 return get_impl_ptr(static_cast<PointerType>(nullptr));
21059 }
21060
21061 private:
21100 template < typename ValueType,
21104 int > = 0 >
21105 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21106 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21107 {
21108 auto ret = ValueType();
21109 JSONSerializer<ValueType>::from_json(*this, ret);
21110 return ret;
21111 }
21112
21143 template < typename ValueType,
21146 int > = 0 >
21147 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21148 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21149 {
21150 return JSONSerializer<ValueType>::from_json(*this);
21151 }
21152
21168 template < typename BasicJsonType,
21171 int > = 0 >
21172 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21173 {
21174 return *this;
21175 }
21176
21191 template<typename BasicJsonType,
21193 std::is_same<BasicJsonType, basic_json_t>::value,
21194 int> = 0>
21195 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21196 {
21197 return *this;
21198 }
21199
21204 template<typename PointerType,
21206 std::is_pointer<PointerType>::value,
21207 int> = 0>
21208 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21209 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21210 {
21211 // delegate the call to get_ptr
21212 return get_ptr<PointerType>();
21213 }
21214
21215 public:
21239 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21240#if defined(JSON_HAS_CPP_14)
21241 constexpr
21242#endif
21243 auto get() const noexcept(
21244 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21245 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21246 {
21247 // we cannot static_assert on ValueTypeCV being non-const, because
21248 // there is support for get<const basic_json_t>(), which is why we
21249 // still need the uncvref
21250 static_assert(!std::is_reference<ValueTypeCV>::value,
21251 "get() cannot be used with reference types, you might want to use get_ref()");
21252 return get_impl<ValueType>(detail::priority_tag<4> {});
21253 }
21254
21282 template<typename PointerType, typename std::enable_if<
21283 std::is_pointer<PointerType>::value, int>::type = 0>
21284 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21285 {
21286 // delegate the call to get_ptr
21287 return get_ptr<PointerType>();
21288 }
21289
21292 template < typename ValueType,
21296 int > = 0 >
21297 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21298 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21299 {
21300 JSONSerializer<ValueType>::from_json(*this, v);
21301 return v;
21302 }
21303
21304 // specialization to allow calling get_to with a basic_json value
21305 // see https://github.com/nlohmann/json/issues/2175
21306 template<typename ValueType,
21309 int> = 0>
21310 ValueType & get_to(ValueType& v) const
21311 {
21312 v = *this;
21313 return v;
21314 }
21315
21316 template <
21317 typename T, std::size_t N,
21318 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21321 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21322 noexcept(noexcept(JSONSerializer<Array>::from_json(
21323 std::declval<const basic_json_t&>(), v)))
21324 {
21325 JSONSerializer<Array>::from_json(*this, v);
21326 return v;
21327 }
21328
21331 template<typename ReferenceType, typename std::enable_if<
21332 std::is_reference<ReferenceType>::value, int>::type = 0>
21333 ReferenceType get_ref()
21334 {
21335 // delegate call to get_ref_impl
21336 return get_ref_impl<ReferenceType>(*this);
21337 }
21338
21341 template < typename ReferenceType, typename std::enable_if <
21342 std::is_reference<ReferenceType>::value&&
21343 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21344 ReferenceType get_ref() const
21345 {
21346 // delegate call to get_ref_impl
21347 return get_ref_impl<ReferenceType>(*this);
21348 }
21349
21379 template < typename ValueType, typename std::enable_if <
21387#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21389#endif
21390#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21392#endif
21394 >::value, int >::type = 0 >
21395 JSON_EXPLICIT operator ValueType() const
21396 {
21397 // delegate the call to get<>() const
21398 return get<ValueType>();
21399 }
21400
21404 {
21405 if (!is_binary())
21406 {
21407 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21408 }
21409
21410 return *get_ptr<binary_t*>();
21411 }
21412
21415 const binary_t& get_binary() const
21416 {
21417 if (!is_binary())
21418 {
21419 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21420 }
21421
21422 return *get_ptr<const binary_t*>();
21423 }
21424
21426
21428 // element access //
21430
21434
21438 {
21439 // at only works for arrays
21441 {
21442 JSON_TRY
21443 {
21444 return set_parent(m_data.m_value.array->at(idx));
21445 }
21446 JSON_CATCH (std::out_of_range&)
21447 {
21448 // create better exception explanation
21449 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21450 }
21451 }
21452 else
21453 {
21454 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21455 }
21456 }
21457
21461 {
21462 // at only works for arrays
21464 {
21465 JSON_TRY
21466 {
21467 return m_data.m_value.array->at(idx);
21468 }
21469 JSON_CATCH (std::out_of_range&)
21470 {
21471 // create better exception explanation
21472 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21473 }
21474 }
21475 else
21476 {
21477 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21478 }
21479 }
21480
21483 reference at(const typename object_t::key_type& key)
21484 {
21485 // at only works for objects
21487 {
21488 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21489 }
21490
21491 auto it = m_data.m_value.object->find(key);
21492 if (it == m_data.m_value.object->end())
21493 {
21494 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21495 }
21496 return set_parent(it->second);
21497 }
21498
21501 template<class KeyType, detail::enable_if_t<
21503 reference at(KeyType && key)
21504 {
21505 // at only works for objects
21507 {
21508 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21509 }
21510
21511 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21512 if (it == m_data.m_value.object->end())
21513 {
21514 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21515 }
21516 return set_parent(it->second);
21517 }
21518
21521 const_reference at(const typename object_t::key_type& key) const
21522 {
21523 // at only works for objects
21525 {
21526 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21527 }
21528
21529 auto it = m_data.m_value.object->find(key);
21530 if (it == m_data.m_value.object->end())
21531 {
21532 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21533 }
21534 return it->second;
21535 }
21536
21539 template<class KeyType, detail::enable_if_t<
21541 const_reference at(KeyType && key) const
21542 {
21543 // at only works for objects
21545 {
21546 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21547 }
21548
21549 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21550 if (it == m_data.m_value.object->end())
21551 {
21552 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21553 }
21554 return it->second;
21555 }
21556
21560 {
21561 // implicitly convert null value to an empty array
21562 if (is_null())
21563 {
21564 m_data.m_type = value_t::array;
21565 m_data.m_value.array = create<array_t>();
21566 assert_invariant();
21567 }
21568
21569 // operator[] only works for arrays
21571 {
21572 // fill up array with null values if given idx is outside range
21573 if (idx >= m_data.m_value.array->size())
21574 {
21575#if JSON_DIAGNOSTICS
21576 // remember array size & capacity before resizing
21577 const auto old_size = m_data.m_value.array->size();
21578 const auto old_capacity = m_data.m_value.array->capacity();
21579#endif
21580 m_data.m_value.array->resize(idx + 1);
21581
21582#if JSON_DIAGNOSTICS
21583 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21584 {
21585 // capacity has changed: update all parents
21586 set_parents();
21587 }
21588 else
21589 {
21590 // set parent for values added above
21591 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21592 }
21593#endif
21594 assert_invariant();
21595 }
21596
21597 return m_data.m_value.array->operator[](idx);
21598 }
21599
21600 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21601 }
21602
21606 {
21607 // const operator[] only works for arrays
21609 {
21610 return m_data.m_value.array->operator[](idx);
21611 }
21612
21613 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21614 }
21615
21618 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
21619 {
21620 // implicitly convert null value to an empty object
21621 if (is_null())
21622 {
21623 m_data.m_type = value_t::object;
21624 m_data.m_value.object = create<object_t>();
21625 assert_invariant();
21626 }
21627
21628 // operator[] only works for objects
21630 {
21631 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21632 return set_parent(result.first->second);
21633 }
21634
21635 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21636 }
21637
21640 const_reference operator[](const typename object_t::key_type& key) const
21641 {
21642 // const operator[] only works for objects
21644 {
21645 auto it = m_data.m_value.object->find(key);
21646 JSON_ASSERT(it != m_data.m_value.object->end());
21647 return it->second;
21648 }
21649
21650 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21651 }
21652
21653 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21654 // (they seemingly cannot be constrained to resolve the ambiguity)
21655 template<typename T>
21657 {
21658 return operator[](typename object_t::key_type(key));
21659 }
21660
21661 template<typename T>
21663 {
21664 return operator[](typename object_t::key_type(key));
21665 }
21666
21669 template<class KeyType, detail::enable_if_t<
21671 reference operator[](KeyType && key)
21672 {
21673 // implicitly convert null value to an empty object
21674 if (is_null())
21675 {
21676 m_data.m_type = value_t::object;
21677 m_data.m_value.object = create<object_t>();
21678 assert_invariant();
21679 }
21680
21681 // operator[] only works for objects
21683 {
21684 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21685 return set_parent(result.first->second);
21686 }
21687
21688 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21689 }
21690
21693 template<class KeyType, detail::enable_if_t<
21695 const_reference operator[](KeyType && key) const
21696 {
21697 // const operator[] only works for objects
21699 {
21700 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21701 JSON_ASSERT(it != m_data.m_value.object->end());
21702 return it->second;
21703 }
21704
21705 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21706 }
21707
21708 private:
21709 template<typename KeyType>
21710 using is_comparable_with_object_key = detail::is_comparable <
21711 object_comparator_t, const typename object_t::key_type&, KeyType >;
21712
21713 template<typename ValueType>
21714 using value_return_type = std::conditional <
21716 string_t, typename std::decay<ValueType>::type >;
21717
21718 public:
21721 template < class ValueType, detail::enable_if_t <
21724 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21725 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21726 {
21727 // value only works for objects
21729 {
21730 // if key is found, return value and given default value otherwise
21731 const auto it = find(key);
21732 if (it != end())
21733 {
21734 return it->template get<ValueType>();
21735 }
21736
21737 return default_value;
21738 }
21739
21740 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21741 }
21742
21745 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21749 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21750 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21751 {
21752 // value only works for objects
21754 {
21755 // if key is found, return value and given default value otherwise
21756 const auto it = find(key);
21757 if (it != end())
21758 {
21759 return it->template get<ReturnType>();
21760 }
21761
21762 return std::forward<ValueType>(default_value);
21763 }
21764
21765 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21766 }
21767
21770 template < class ValueType, class KeyType, detail::enable_if_t <
21773 && is_comparable_with_object_key<KeyType>::value
21775 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21776 ValueType value(KeyType && key, const ValueType& default_value) const
21777 {
21778 // value only works for objects
21780 {
21781 // if key is found, return value and given default value otherwise
21782 const auto it = find(std::forward<KeyType>(key));
21783 if (it != end())
21784 {
21785 return it->template get<ValueType>();
21786 }
21787
21788 return default_value;
21789 }
21790
21791 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21792 }
21793
21796 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21800 && is_comparable_with_object_key<KeyType>::value
21802 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21803 ReturnType value(KeyType && key, ValueType && default_value) const
21804 {
21805 // value only works for objects
21807 {
21808 // if key is found, return value and given default value otherwise
21809 const auto it = find(std::forward<KeyType>(key));
21810 if (it != end())
21811 {
21812 return it->template get<ReturnType>();
21813 }
21814
21815 return std::forward<ValueType>(default_value);
21816 }
21817
21818 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21819 }
21820
21823 template < class ValueType, detail::enable_if_t <
21825 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21826 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21827 {
21828 // value only works for objects
21830 {
21831 // if pointer resolves a value, return it or use default value
21832 JSON_TRY
21833 {
21834 return ptr.get_checked(this).template get<ValueType>();
21835 }
21837 {
21838 return default_value;
21839 }
21840 }
21841
21842 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21843 }
21844
21847 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21850 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21851 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21852 {
21853 // value only works for objects
21855 {
21856 // if pointer resolves a value, return it or use default value
21857 JSON_TRY
21858 {
21859 return ptr.get_checked(this).template get<ReturnType>();
21860 }
21862 {
21863 return std::forward<ValueType>(default_value);
21864 }
21865 }
21866
21867 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21868 }
21869
21870 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21873 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21874 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21875 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21876 {
21877 return value(ptr.convert(), default_value);
21878 }
21879
21880 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21884 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21885 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21886 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21887 {
21888 return value(ptr.convert(), std::forward<ValueType>(default_value));
21889 }
21890
21894 {
21895 return *begin();
21896 }
21897
21901 {
21902 return *cbegin();
21903 }
21904
21908 {
21909 auto tmp = end();
21910 --tmp;
21911 return *tmp;
21912 }
21913
21917 {
21918 auto tmp = cend();
21919 --tmp;
21920 return *tmp;
21921 }
21922
21925 template < class IteratorType, detail::enable_if_t <
21926 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21927 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21928 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
21929 {
21930 // make sure iterator fits the current value
21931 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21932 {
21933 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21934 }
21935
21936 IteratorType result = end();
21937
21938 switch (m_data.m_type)
21939 {
21940 case value_t::boolean:
21941 case value_t::number_float:
21942 case value_t::number_integer:
21943 case value_t::number_unsigned:
21944 case value_t::string:
21945 case value_t::binary:
21946 {
21947 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21948 {
21949 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21950 }
21951
21952 if (is_string())
21953 {
21954 AllocatorType<string_t> alloc;
21955 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21956 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21957 m_data.m_value.string = nullptr;
21958 }
21959 else if (is_binary())
21960 {
21961 AllocatorType<binary_t> alloc;
21962 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21963 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21964 m_data.m_value.binary = nullptr;
21965 }
21966
21967 m_data.m_type = value_t::null;
21968 assert_invariant();
21969 break;
21970 }
21971
21972 case value_t::object:
21973 {
21974 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21975 break;
21976 }
21977
21978 case value_t::array:
21979 {
21980 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21981 break;
21982 }
21983
21984 case value_t::null:
21985 case value_t::discarded:
21986 default:
21987 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21988 }
21989
21990 return result;
21991 }
21992
21995 template < class IteratorType, detail::enable_if_t <
21996 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21997 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21998 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
21999 {
22000 // make sure iterator fits the current value
22001 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22002 {
22003 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22004 }
22005
22006 IteratorType result = end();
22007
22008 switch (m_data.m_type)
22009 {
22010 case value_t::boolean:
22011 case value_t::number_float:
22012 case value_t::number_integer:
22013 case value_t::number_unsigned:
22014 case value_t::string:
22015 case value_t::binary:
22016 {
22017 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22018 || !last.m_it.primitive_iterator.is_end()))
22019 {
22020 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22021 }
22022
22023 if (is_string())
22024 {
22025 AllocatorType<string_t> alloc;
22026 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22027 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22028 m_data.m_value.string = nullptr;
22029 }
22030 else if (is_binary())
22031 {
22032 AllocatorType<binary_t> alloc;
22033 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22034 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22035 m_data.m_value.binary = nullptr;
22036 }
22037
22038 m_data.m_type = value_t::null;
22039 assert_invariant();
22040 break;
22041 }
22042
22043 case value_t::object:
22044 {
22045 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22046 last.m_it.object_iterator);
22047 break;
22048 }
22049
22050 case value_t::array:
22051 {
22052 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22053 last.m_it.array_iterator);
22054 break;
22055 }
22056
22057 case value_t::null:
22058 case value_t::discarded:
22059 default:
22060 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22061 }
22062
22063 return result;
22064 }
22065
22066 private:
22067 template < typename KeyType, detail::enable_if_t <
22069 size_type erase_internal(KeyType && key)
22070 {
22071 // this erase only works for objects
22073 {
22074 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22075 }
22076
22077 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22078 }
22079
22080 template < typename KeyType, detail::enable_if_t <
22082 size_type erase_internal(KeyType && key)
22083 {
22084 // this erase only works for objects
22086 {
22087 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22088 }
22089
22090 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22091 if (it != m_data.m_value.object->end())
22092 {
22093 m_data.m_value.object->erase(it);
22094 return 1;
22095 }
22096 return 0;
22097 }
22098
22099 public:
22100
22103 size_type erase(const typename object_t::key_type& key)
22104 {
22105 // the indirection via erase_internal() is added to avoid making this
22106 // function a template and thus de-rank it during overload resolution
22107 return erase_internal(key);
22108 }
22109
22112 template<class KeyType, detail::enable_if_t<
22114 size_type erase(KeyType && key)
22115 {
22116 return erase_internal(std::forward<KeyType>(key));
22117 }
22118
22121 void erase(const size_type idx)
22122 {
22123 // this erase only works for arrays
22125 {
22126 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22127 {
22128 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22129 }
22130
22131 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22132 }
22133 else
22134 {
22135 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22136 }
22137 }
22138
22140
22142 // lookup //
22144
22147
22150 iterator find(const typename object_t::key_type& key)
22151 {
22152 auto result = end();
22153
22154 if (is_object())
22155 {
22156 result.m_it.object_iterator = m_data.m_value.object->find(key);
22157 }
22158
22159 return result;
22160 }
22161
22164 const_iterator find(const typename object_t::key_type& key) const
22165 {
22166 auto result = cend();
22167
22168 if (is_object())
22169 {
22170 result.m_it.object_iterator = m_data.m_value.object->find(key);
22171 }
22172
22173 return result;
22174 }
22175
22178 template<class KeyType, detail::enable_if_t<
22180 iterator find(KeyType && key)
22181 {
22182 auto result = end();
22183
22184 if (is_object())
22185 {
22186 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22187 }
22188
22189 return result;
22190 }
22191
22194 template<class KeyType, detail::enable_if_t<
22196 const_iterator find(KeyType && key) const
22197 {
22198 auto result = cend();
22199
22200 if (is_object())
22201 {
22202 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22203 }
22204
22205 return result;
22206 }
22207
22210 size_type count(const typename object_t::key_type& key) const
22211 {
22212 // return 0 for all nonobject types
22213 return is_object() ? m_data.m_value.object->count(key) : 0;
22214 }
22215
22218 template<class KeyType, detail::enable_if_t<
22220 size_type count(KeyType && key) const
22221 {
22222 // return 0 for all nonobject types
22223 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22224 }
22225
22228 bool contains(const typename object_t::key_type& key) const
22229 {
22230 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22231 }
22232
22235 template<class KeyType, detail::enable_if_t<
22237 bool contains(KeyType && key) const
22238 {
22239 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22240 }
22241
22244 bool contains(const json_pointer& ptr) const
22245 {
22246 return ptr.contains(this);
22247 }
22248
22249 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22250 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22251 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22252 {
22253 return ptr.contains(this);
22254 }
22255
22257
22259 // iterators //
22261
22264
22267 iterator begin() noexcept
22268 {
22269 iterator result(this);
22270 result.set_begin();
22271 return result;
22272 }
22273
22276 const_iterator begin() const noexcept
22277 {
22278 return cbegin();
22279 }
22280
22283 const_iterator cbegin() const noexcept
22284 {
22285 const_iterator result(this);
22286 result.set_begin();
22287 return result;
22288 }
22289
22292 iterator end() noexcept
22293 {
22294 iterator result(this);
22295 result.set_end();
22296 return result;
22297 }
22298
22301 const_iterator end() const noexcept
22302 {
22303 return cend();
22304 }
22305
22308 const_iterator cend() const noexcept
22309 {
22310 const_iterator result(this);
22311 result.set_end();
22312 return result;
22313 }
22314
22318 {
22319 return reverse_iterator(end());
22320 }
22321
22325 {
22326 return crbegin();
22327 }
22328
22332 {
22333 return reverse_iterator(begin());
22334 }
22335
22339 {
22340 return crend();
22341 }
22342
22346 {
22347 return const_reverse_iterator(cend());
22348 }
22349
22353 {
22355 }
22356
22357 public:
22364 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22365 {
22366 return ref.items();
22367 }
22368
22375 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22376 {
22377 return ref.items();
22378 }
22379
22382 iteration_proxy<iterator> items() noexcept
22383 {
22384 return iteration_proxy<iterator>(*this);
22385 }
22386
22389 iteration_proxy<const_iterator> items() const noexcept
22390 {
22391 return iteration_proxy<const_iterator>(*this);
22392 }
22393
22395
22397 // capacity //
22399
22402
22405 bool empty() const noexcept
22406 {
22407 switch (m_data.m_type)
22408 {
22409 case value_t::null:
22410 {
22411 // null values are empty
22412 return true;
22413 }
22414
22415 case value_t::array:
22416 {
22417 // delegate call to array_t::empty()
22418 return m_data.m_value.array->empty();
22419 }
22420
22421 case value_t::object:
22422 {
22423 // delegate call to object_t::empty()
22424 return m_data.m_value.object->empty();
22425 }
22426
22427 case value_t::string:
22428 case value_t::boolean:
22429 case value_t::number_integer:
22430 case value_t::number_unsigned:
22431 case value_t::number_float:
22432 case value_t::binary:
22433 case value_t::discarded:
22434 default:
22435 {
22436 // all other types are nonempty
22437 return false;
22438 }
22439 }
22440 }
22441
22444 size_type size() const noexcept
22445 {
22446 switch (m_data.m_type)
22447 {
22448 case value_t::null:
22449 {
22450 // null values are empty
22451 return 0;
22452 }
22453
22454 case value_t::array:
22455 {
22456 // delegate call to array_t::size()
22457 return m_data.m_value.array->size();
22458 }
22459
22460 case value_t::object:
22461 {
22462 // delegate call to object_t::size()
22463 return m_data.m_value.object->size();
22464 }
22465
22466 case value_t::string:
22467 case value_t::boolean:
22468 case value_t::number_integer:
22469 case value_t::number_unsigned:
22470 case value_t::number_float:
22471 case value_t::binary:
22472 case value_t::discarded:
22473 default:
22474 {
22475 // all other types have size 1
22476 return 1;
22477 }
22478 }
22479 }
22480
22483 size_type max_size() const noexcept
22484 {
22485 switch (m_data.m_type)
22486 {
22487 case value_t::array:
22488 {
22489 // delegate call to array_t::max_size()
22490 return m_data.m_value.array->max_size();
22491 }
22492
22493 case value_t::object:
22494 {
22495 // delegate call to object_t::max_size()
22496 return m_data.m_value.object->max_size();
22497 }
22498
22499 case value_t::null:
22500 case value_t::string:
22501 case value_t::boolean:
22502 case value_t::number_integer:
22503 case value_t::number_unsigned:
22504 case value_t::number_float:
22505 case value_t::binary:
22506 case value_t::discarded:
22507 default:
22508 {
22509 // all other types have max_size() == size()
22510 return size();
22511 }
22512 }
22513 }
22514
22516
22518 // modifiers //
22520
22523
22526 void clear() noexcept
22527 {
22528 switch (m_data.m_type)
22529 {
22530 case value_t::number_integer:
22531 {
22532 m_data.m_value.number_integer = 0;
22533 break;
22534 }
22535
22536 case value_t::number_unsigned:
22537 {
22538 m_data.m_value.number_unsigned = 0;
22539 break;
22540 }
22541
22542 case value_t::number_float:
22543 {
22544 m_data.m_value.number_float = 0.0;
22545 break;
22546 }
22547
22548 case value_t::boolean:
22549 {
22550 m_data.m_value.boolean = false;
22551 break;
22552 }
22553
22554 case value_t::string:
22555 {
22556 m_data.m_value.string->clear();
22557 break;
22558 }
22559
22560 case value_t::binary:
22561 {
22562 m_data.m_value.binary->clear();
22563 break;
22564 }
22565
22566 case value_t::array:
22567 {
22568 m_data.m_value.array->clear();
22569 break;
22570 }
22571
22572 case value_t::object:
22573 {
22574 m_data.m_value.object->clear();
22575 break;
22576 }
22577
22578 case value_t::null:
22579 case value_t::discarded:
22580 default:
22581 break;
22582 }
22583 }
22584
22588 {
22589 // push_back only works for null objects or arrays
22590 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22591 {
22592 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22593 }
22594
22595 // transform null object into an array
22596 if (is_null())
22597 {
22598 m_data.m_type = value_t::array;
22599 m_data.m_value = value_t::array;
22600 assert_invariant();
22601 }
22602
22603 // add element to array (move semantics)
22604 const auto old_capacity = m_data.m_value.array->capacity();
22605 m_data.m_value.array->push_back(std::move(val));
22606 set_parent(m_data.m_value.array->back(), old_capacity);
22607 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22608 }
22609
22613 {
22614 push_back(std::move(val));
22615 return *this;
22616 }
22617
22620 void push_back(const basic_json& val)
22621 {
22622 // push_back only works for null objects or arrays
22623 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22624 {
22625 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22626 }
22627
22628 // transform null object into an array
22629 if (is_null())
22630 {
22631 m_data.m_type = value_t::array;
22632 m_data.m_value = value_t::array;
22633 assert_invariant();
22634 }
22635
22636 // add element to array
22637 const auto old_capacity = m_data.m_value.array->capacity();
22638 m_data.m_value.array->push_back(val);
22639 set_parent(m_data.m_value.array->back(), old_capacity);
22640 }
22641
22645 {
22646 push_back(val);
22647 return *this;
22648 }
22649
22652 void push_back(const typename object_t::value_type& val)
22653 {
22654 // push_back only works for null objects or objects
22655 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22656 {
22657 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22658 }
22659
22660 // transform null object into an object
22661 if (is_null())
22662 {
22663 m_data.m_type = value_t::object;
22664 m_data.m_value = value_t::object;
22665 assert_invariant();
22666 }
22667
22668 // add element to object
22669 auto res = m_data.m_value.object->insert(val);
22670 set_parent(res.first->second);
22671 }
22672
22675 reference operator+=(const typename object_t::value_type& val)
22676 {
22677 push_back(val);
22678 return *this;
22679 }
22680
22684 {
22685 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22686 {
22687 basic_json&& key = init.begin()->moved_or_copied();
22688 push_back(typename object_t::value_type(
22689 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22690 }
22691 else
22692 {
22693 push_back(basic_json(init));
22694 }
22695 }
22696
22700 {
22701 push_back(init);
22702 return *this;
22703 }
22704
22707 template<class... Args>
22708 reference emplace_back(Args&& ... args)
22709 {
22710 // emplace_back only works for null objects or arrays
22711 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22712 {
22713 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22714 }
22715
22716 // transform null object into an array
22717 if (is_null())
22718 {
22719 m_data.m_type = value_t::array;
22720 m_data.m_value = value_t::array;
22721 assert_invariant();
22722 }
22723
22724 // add element to array (perfect forwarding)
22725 const auto old_capacity = m_data.m_value.array->capacity();
22726 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22727 return set_parent(m_data.m_value.array->back(), old_capacity);
22728 }
22729
22732 template<class... Args>
22733 std::pair<iterator, bool> emplace(Args&& ... args)
22734 {
22735 // emplace only works for null objects or arrays
22736 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22737 {
22738 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22739 }
22740
22741 // transform null object into an object
22742 if (is_null())
22743 {
22744 m_data.m_type = value_t::object;
22745 m_data.m_value = value_t::object;
22746 assert_invariant();
22747 }
22748
22749 // add element to array (perfect forwarding)
22750 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22751 set_parent(res.first->second);
22752
22753 // create result iterator and set iterator to the result of emplace
22754 auto it = begin();
22755 it.m_it.object_iterator = res.first;
22756
22757 // return pair of iterator and boolean
22758 return {it, res.second};
22759 }
22760
22764 template<typename... Args>
22765 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
22766 {
22767 iterator result(this);
22768 JSON_ASSERT(m_data.m_value.array != nullptr);
22769
22770 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22771 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22772 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22773
22774 // This could have been written as:
22775 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22776 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22777
22778 set_parents();
22779 return result;
22780 }
22781
22784 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
22785 {
22786 // insert only works for arrays
22788 {
22789 // check if iterator pos fits to this JSON value
22790 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22791 {
22792 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22793 }
22794
22795 // insert to array and return iterator
22796 return insert_iterator(pos, val);
22797 }
22798
22799 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22800 }
22801
22804 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
22805 {
22806 return insert(pos, val);
22807 }
22808
22811 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
22812 {
22813 // insert only works for arrays
22815 {
22816 // check if iterator pos fits to this JSON value
22817 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22818 {
22819 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22820 }
22821
22822 // insert to array and return iterator
22823 return insert_iterator(pos, cnt, val);
22824 }
22825
22826 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22827 }
22828
22831 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
22832 {
22833 // insert only works for arrays
22835 {
22836 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22837 }
22838
22839 // check if iterator pos fits to this JSON value
22840 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22841 {
22842 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22843 }
22844
22845 // check if range iterators belong to the same JSON object
22846 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22847 {
22848 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22849 }
22850
22851 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22852 {
22853 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22854 }
22855
22856 // insert to array and return iterator
22857 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22858 }
22859
22862 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
22863 {
22864 // insert only works for arrays
22866 {
22867 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22868 }
22869
22870 // check if iterator pos fits to this JSON value
22871 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22872 {
22873 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22874 }
22875
22876 // insert to array and return iterator
22877 return insert_iterator(pos, ilist.begin(), ilist.end());
22878 }
22879
22882 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
22883 {
22884 // insert only works for objects
22886 {
22887 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22888 }
22889
22890 // check if range iterators belong to the same JSON object
22891 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22892 {
22893 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22894 }
22895
22896 // passed iterators must belong to objects
22897 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22898 {
22899 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22900 }
22901
22902 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22903 }
22904
22907 void update(const_reference j, bool merge_objects = false)
22908 {
22909 update(j.begin(), j.end(), merge_objects);
22910 }
22911
22914 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
22915 {
22916 // implicitly convert null value to an empty object
22917 if (is_null())
22918 {
22919 m_data.m_type = value_t::object;
22920 m_data.m_value.object = create<object_t>();
22921 assert_invariant();
22922 }
22923
22925 {
22926 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22927 }
22928
22929 // check if range iterators belong to the same JSON object
22930 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22931 {
22932 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22933 }
22934
22935 // passed iterators must belong to objects
22936 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22937 {
22938 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22939 }
22940
22941 for (auto it = first; it != last; ++it)
22942 {
22943 if (merge_objects && it.value().is_object())
22944 {
22945 auto it2 = m_data.m_value.object->find(it.key());
22946 if (it2 != m_data.m_value.object->end())
22947 {
22948 it2->second.update(it.value(), true);
22949 continue;
22950 }
22951 }
22952 m_data.m_value.object->operator[](it.key()) = it.value();
22953#if JSON_DIAGNOSTICS
22954 m_data.m_value.object->operator[](it.key()).m_parent = this;
22955#endif
22956 }
22957 }
22958
22961 void swap(reference other) noexcept (
22962 std::is_nothrow_move_constructible<value_t>::value&&
22963 std::is_nothrow_move_assignable<value_t>::value&&
22964 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22965 std::is_nothrow_move_assignable<json_value>::value
22966 )
22967 {
22968 std::swap(m_data.m_type, other.m_data.m_type);
22969 std::swap(m_data.m_value, other.m_data.m_value);
22970
22971 set_parents();
22972 other.set_parents();
22973 assert_invariant();
22974 }
22975
22978 friend void swap(reference left, reference right) noexcept (
22979 std::is_nothrow_move_constructible<value_t>::value&&
22980 std::is_nothrow_move_assignable<value_t>::value&&
22981 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22982 std::is_nothrow_move_assignable<json_value>::value
22983 )
22984 {
22985 left.swap(right);
22986 }
22987
22990 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22991 {
22992 // swap only works for arrays
22994 {
22995 using std::swap;
22996 swap(*(m_data.m_value.array), other);
22997 }
22998 else
22999 {
23000 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23001 }
23002 }
23003
23006 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23007 {
23008 // swap only works for objects
23010 {
23011 using std::swap;
23012 swap(*(m_data.m_value.object), other);
23013 }
23014 else
23015 {
23016 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23017 }
23018 }
23019
23022 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23023 {
23024 // swap only works for strings
23026 {
23027 using std::swap;
23028 swap(*(m_data.m_value.string), other);
23029 }
23030 else
23031 {
23032 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23033 }
23034 }
23035
23038 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23039 {
23040 // swap only works for strings
23042 {
23043 using std::swap;
23044 swap(*(m_data.m_value.binary), other);
23045 }
23046 else
23047 {
23048 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23049 }
23050 }
23051
23054 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23055 {
23056 // swap only works for strings
23058 {
23059 using std::swap;
23060 swap(*(m_data.m_value.binary), other);
23061 }
23062 else
23063 {
23064 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23065 }
23066 }
23067
23069
23071 // lexicographical comparison operators //
23073
23076
23077 // note parentheses around operands are necessary; see
23078 // https://github.com/nlohmann/json/issues/1530
23079#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23080 const auto lhs_type = lhs.type(); \
23081 const auto rhs_type = rhs.type(); \
23082 \
23083 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23084 { \
23085 switch (lhs_type) \
23086 { \
23087 case value_t::array: \
23088 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23089 \
23090 case value_t::object: \
23091 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23092 \
23093 case value_t::null: \
23094 return (null_result); \
23095 \
23096 case value_t::string: \
23097 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23098 \
23099 case value_t::boolean: \
23100 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23101 \
23102 case value_t::number_integer: \
23103 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23104 \
23105 case value_t::number_unsigned: \
23106 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23107 \
23108 case value_t::number_float: \
23109 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23110 \
23111 case value_t::binary: \
23112 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23113 \
23114 case value_t::discarded: \
23115 default: \
23116 return (unordered_result); \
23117 } \
23118 } \
23119 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23120 { \
23121 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23122 } \
23123 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23124 { \
23125 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23126 } \
23127 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23128 { \
23129 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23130 } \
23131 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23132 { \
23133 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23134 } \
23135 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23136 { \
23137 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23138 } \
23139 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23140 { \
23141 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23142 } \
23143 else if(compares_unordered(lhs, rhs))\
23144 {\
23145 return (unordered_result);\
23146 }\
23147 \
23148 return (default_result);
23149
23151 // returns true if:
23152 // - any operand is NaN and the other operand is of number type
23153 // - any operand is discarded
23154 // in legacy mode, discarded values are considered ordered if
23155 // an operation is computed as an odd number of inverses of others
23156 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23157 {
23158 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23159 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23160 {
23161 return true;
23162 }
23163#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23164 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23165#else
23166 static_cast<void>(inverse);
23167 return lhs.is_discarded() || rhs.is_discarded();
23168#endif
23169 }
23170
23171 private:
23172 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23173 {
23174 return compares_unordered(*this, rhs, inverse);
23175 }
23176
23177 public:
23178#if JSON_HAS_THREE_WAY_COMPARISON
23181 bool operator==(const_reference rhs) const noexcept
23182 {
23183#ifdef __GNUC__
23184#pragma GCC diagnostic push
23185#pragma GCC diagnostic ignored "-Wfloat-equal"
23186#endif
23187 const_reference lhs = *this;
23188 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23189#ifdef __GNUC__
23190#pragma GCC diagnostic pop
23191#endif
23192 }
23193
23196 template<typename ScalarType>
23197 requires std::is_scalar_v<ScalarType>
23198 bool operator==(ScalarType rhs) const noexcept
23199 {
23200 return *this == basic_json(rhs);
23201 }
23202
23205 bool operator!=(const_reference rhs) const noexcept
23206 {
23207 if (compares_unordered(rhs, true))
23208 {
23209 return false;
23210 }
23211 return !operator==(rhs);
23212 }
23213
23216 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23217 {
23218 const_reference lhs = *this;
23219 // default_result is used if we cannot compare values. In that case,
23220 // we compare types.
23221 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23222 std::partial_ordering::equivalent,
23223 std::partial_ordering::unordered,
23224 lhs_type <=> rhs_type) // *NOPAD*
23225 }
23226
23229 template<typename ScalarType>
23230 requires std::is_scalar_v<ScalarType>
23231 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23232 {
23233 return *this <=> basic_json(rhs); // *NOPAD*
23234 }
23235
23236#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23237 // all operators that are computed as an odd number of inverses of others
23238 // need to be overloaded to emulate the legacy comparison behavior
23239
23243 bool operator<=(const_reference rhs) const noexcept
23244 {
23245 if (compares_unordered(rhs, true))
23246 {
23247 return false;
23248 }
23249 return !(rhs < *this);
23250 }
23251
23254 template<typename ScalarType>
23255 requires std::is_scalar_v<ScalarType>
23256 bool operator<=(ScalarType rhs) const noexcept
23257 {
23258 return *this <= basic_json(rhs);
23259 }
23260
23264 bool operator>=(const_reference rhs) const noexcept
23265 {
23266 if (compares_unordered(rhs, true))
23267 {
23268 return false;
23269 }
23270 return !(*this < rhs);
23271 }
23272
23275 template<typename ScalarType>
23276 requires std::is_scalar_v<ScalarType>
23277 bool operator>=(ScalarType rhs) const noexcept
23278 {
23279 return *this >= basic_json(rhs);
23280 }
23281#endif
23282#else
23285 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23286 {
23287#ifdef __GNUC__
23288#pragma GCC diagnostic push
23289#pragma GCC diagnostic ignored "-Wfloat-equal"
23290#endif
23291 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23292#ifdef __GNUC__
23293#pragma GCC diagnostic pop
23294#endif
23295 }
23296
23299 template<typename ScalarType, typename std::enable_if<
23300 std::is_scalar<ScalarType>::value, int>::type = 0>
23301 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23302 {
23303 return lhs == basic_json(rhs);
23304 }
23305
23308 template<typename ScalarType, typename std::enable_if<
23309 std::is_scalar<ScalarType>::value, int>::type = 0>
23310 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23311 {
23312 return basic_json(lhs) == rhs;
23313 }
23314
23317 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23318 {
23319 if (compares_unordered(lhs, rhs, true))
23320 {
23321 return false;
23322 }
23323 return !(lhs == rhs);
23324 }
23325
23328 template<typename ScalarType, typename std::enable_if<
23329 std::is_scalar<ScalarType>::value, int>::type = 0>
23330 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23331 {
23332 return lhs != basic_json(rhs);
23333 }
23334
23337 template<typename ScalarType, typename std::enable_if<
23338 std::is_scalar<ScalarType>::value, int>::type = 0>
23339 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23340 {
23341 return basic_json(lhs) != rhs;
23342 }
23343
23346 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23347 {
23348 // default_result is used if we cannot compare values. In that case,
23349 // we compare types. Note we have to call the operator explicitly,
23350 // because MSVC has problems otherwise.
23351 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23352 }
23353
23356 template<typename ScalarType, typename std::enable_if<
23357 std::is_scalar<ScalarType>::value, int>::type = 0>
23358 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23359 {
23360 return lhs < basic_json(rhs);
23361 }
23362
23365 template<typename ScalarType, typename std::enable_if<
23366 std::is_scalar<ScalarType>::value, int>::type = 0>
23367 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23368 {
23369 return basic_json(lhs) < rhs;
23370 }
23371
23374 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23375 {
23376 if (compares_unordered(lhs, rhs, true))
23377 {
23378 return false;
23379 }
23380 return !(rhs < lhs);
23381 }
23382
23385 template<typename ScalarType, typename std::enable_if<
23386 std::is_scalar<ScalarType>::value, int>::type = 0>
23387 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23388 {
23389 return lhs <= basic_json(rhs);
23390 }
23391
23394 template<typename ScalarType, typename std::enable_if<
23395 std::is_scalar<ScalarType>::value, int>::type = 0>
23396 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23397 {
23398 return basic_json(lhs) <= rhs;
23399 }
23400
23403 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23404 {
23405 // double inverse
23406 if (compares_unordered(lhs, rhs))
23407 {
23408 return false;
23409 }
23410 return !(lhs <= rhs);
23411 }
23412
23415 template<typename ScalarType, typename std::enable_if<
23416 std::is_scalar<ScalarType>::value, int>::type = 0>
23417 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23418 {
23419 return lhs > basic_json(rhs);
23420 }
23421
23424 template<typename ScalarType, typename std::enable_if<
23425 std::is_scalar<ScalarType>::value, int>::type = 0>
23426 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23427 {
23428 return basic_json(lhs) > rhs;
23429 }
23430
23433 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23434 {
23435 if (compares_unordered(lhs, rhs, true))
23436 {
23437 return false;
23438 }
23439 return !(lhs < rhs);
23440 }
23441
23444 template<typename ScalarType, typename std::enable_if<
23445 std::is_scalar<ScalarType>::value, int>::type = 0>
23446 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23447 {
23448 return lhs >= basic_json(rhs);
23449 }
23450
23453 template<typename ScalarType, typename std::enable_if<
23454 std::is_scalar<ScalarType>::value, int>::type = 0>
23455 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23456 {
23457 return basic_json(lhs) >= rhs;
23458 }
23459#endif
23460
23461#undef JSON_IMPLEMENT_OPERATOR
23462
23464
23466 // serialization //
23468
23471#ifndef JSON_NO_IO
23474 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23475 {
23476 // read width member and use it as indentation parameter if nonzero
23477 const bool pretty_print = o.width() > 0;
23478 const auto indentation = pretty_print ? o.width() : 0;
23479
23480 // reset width to 0 for subsequent calls to this stream
23481 o.width(0);
23482
23483 // do the actual serialization
23484 serializer s(detail::output_adapter<char>(o), o.fill());
23485 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23486 return o;
23487 }
23488
23495 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23496 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23497 {
23498 return o << j;
23499 }
23500#endif // JSON_NO_IO
23502
23504 // deserialization //
23506
23509
23512 template<typename InputType>
23514 static basic_json parse(InputType&& i,
23515 parser_callback_t cb = nullptr,
23516 const bool allow_exceptions = true,
23517 const bool ignore_comments = false)
23518 {
23519 basic_json result;
23520 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23521 return result;
23522 }
23523
23526 template<typename IteratorType>
23528 static basic_json parse(IteratorType first,
23529 IteratorType last,
23530 parser_callback_t cb = nullptr,
23531 const bool allow_exceptions = true,
23532 const bool ignore_comments = false)
23533 {
23534 basic_json result;
23535 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23536 return result;
23537 }
23538
23540 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23541 static basic_json parse(detail::span_input_adapter&& i,
23542 parser_callback_t cb = nullptr,
23543 const bool allow_exceptions = true,
23544 const bool ignore_comments = false)
23545 {
23546 basic_json result;
23547 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23548 return result;
23549 }
23550
23553 template<typename InputType>
23554 static bool accept(InputType&& i,
23555 const bool ignore_comments = false)
23556 {
23557 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23558 }
23559
23562 template<typename IteratorType>
23563 static bool accept(IteratorType first, IteratorType last,
23564 const bool ignore_comments = false)
23565 {
23566 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23567 }
23568
23570 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23571 static bool accept(detail::span_input_adapter&& i,
23572 const bool ignore_comments = false)
23573 {
23574 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23575 }
23576
23579 template <typename InputType, typename SAX>
23581 static bool sax_parse(InputType&& i, SAX* sax,
23582 input_format_t format = input_format_t::json,
23583 const bool strict = true,
23584 const bool ignore_comments = false)
23585 {
23586 auto ia = detail::input_adapter(std::forward<InputType>(i));
23587 return format == input_format_t::json
23588 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23590 }
23591
23594 template<class IteratorType, class SAX>
23596 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23597 input_format_t format = input_format_t::json,
23598 const bool strict = true,
23599 const bool ignore_comments = false)
23600 {
23601 auto ia = detail::input_adapter(std::move(first), std::move(last));
23602 return format == input_format_t::json
23603 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23605 }
23606
23612 template <typename SAX>
23613 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23615 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23616 input_format_t format = input_format_t::json,
23617 const bool strict = true,
23618 const bool ignore_comments = false)
23619 {
23620 auto ia = i.get();
23621 return format == input_format_t::json
23622 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23623 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23624 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23626 }
23627#ifndef JSON_NO_IO
23634 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23635 friend std::istream& operator<<(basic_json& j, std::istream& i)
23636 {
23637 return operator>>(i, j);
23638 }
23639
23642 friend std::istream& operator>>(std::istream& i, basic_json& j)
23643 {
23644 parser(detail::input_adapter(i)).parse(false, j);
23645 return i;
23646 }
23647#endif // JSON_NO_IO
23649
23651 // convenience functions //
23653
23657 const char* type_name() const noexcept
23658 {
23659 switch (m_data.m_type)
23660 {
23661 case value_t::null:
23662 return "null";
23663 case value_t::object:
23664 return "object";
23665 case value_t::array:
23666 return "array";
23667 case value_t::string:
23668 return "string";
23669 case value_t::boolean:
23670 return "boolean";
23671 case value_t::binary:
23672 return "binary";
23673 case value_t::discarded:
23674 return "discarded";
23675 case value_t::number_integer:
23676 case value_t::number_unsigned:
23677 case value_t::number_float:
23678 default:
23679 return "number";
23680 }
23681 }
23682
23685 // member variables //
23687
23688 struct data
23689 {
23691 value_t m_type = value_t::null;
23692
23694 json_value m_value = {};
23695
23697 : m_type(v), m_value(v)
23698 {
23699 }
23700
23701 data(size_type cnt, const basic_json& val)
23702 : m_type(value_t::array)
23703 {
23704 m_value.array = create<array_t>(cnt, val);
23705 }
23706
23707 data() noexcept = default;
23708 data(data&&) noexcept = default;
23709 data(const data&) noexcept = delete;
23710 data& operator=(data&&) noexcept = delete;
23711 data& operator=(const data&) noexcept = delete;
23712
23713 ~data() noexcept
23714 {
23715 m_value.destroy(m_type);
23716 }
23717 };
23718
23720
23721#if JSON_DIAGNOSTICS
23723 basic_json* m_parent = nullptr;
23724#endif
23725
23727 // binary serialization/deserialization //
23729
23732
23733 public:
23736 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23737 {
23738 std::vector<std::uint8_t> result;
23739 to_cbor(j, result);
23740 return result;
23741 }
23742
23745 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23746 {
23747 binary_writer<std::uint8_t>(o).write_cbor(j);
23748 }
23749
23752 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23753 {
23754 binary_writer<char>(o).write_cbor(j);
23755 }
23756
23759 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23760 {
23761 std::vector<std::uint8_t> result;
23762 to_msgpack(j, result);
23763 return result;
23764 }
23765
23768 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23769 {
23770 binary_writer<std::uint8_t>(o).write_msgpack(j);
23771 }
23772
23775 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23776 {
23777 binary_writer<char>(o).write_msgpack(j);
23778 }
23779
23782 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23783 const bool use_size = false,
23784 const bool use_type = false)
23785 {
23786 std::vector<std::uint8_t> result;
23787 to_ubjson(j, result, use_size, use_type);
23788 return result;
23789 }
23790
23793 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23794 const bool use_size = false, const bool use_type = false)
23795 {
23796 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23797 }
23798
23801 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23802 const bool use_size = false, const bool use_type = false)
23803 {
23804 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23805 }
23806
23809 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23810 const bool use_size = false,
23811 const bool use_type = false)
23812 {
23813 std::vector<std::uint8_t> result;
23814 to_bjdata(j, result, use_size, use_type);
23815 return result;
23816 }
23817
23820 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23821 const bool use_size = false, const bool use_type = false)
23822 {
23823 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23824 }
23825
23828 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
23829 const bool use_size = false, const bool use_type = false)
23830 {
23831 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23832 }
23833
23836 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23837 {
23838 std::vector<std::uint8_t> result;
23839 to_bson(j, result);
23840 return result;
23841 }
23842
23845 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23846 {
23847 binary_writer<std::uint8_t>(o).write_bson(j);
23848 }
23849
23852 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23853 {
23854 binary_writer<char>(o).write_bson(j);
23855 }
23856
23859 template<typename InputType>
23861 static basic_json from_cbor(InputType&& i,
23862 const bool strict = true,
23863 const bool allow_exceptions = true,
23864 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23865 {
23866 basic_json result;
23867 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23868 auto ia = detail::input_adapter(std::forward<InputType>(i));
23869 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23870 return res ? result : basic_json(value_t::discarded);
23871 }
23872
23875 template<typename IteratorType>
23877 static basic_json from_cbor(IteratorType first, IteratorType last,
23878 const bool strict = true,
23879 const bool allow_exceptions = true,
23880 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23881 {
23882 basic_json result;
23883 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23884 auto ia = detail::input_adapter(std::move(first), std::move(last));
23885 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23886 return res ? result : basic_json(value_t::discarded);
23887 }
23888
23889 template<typename T>
23891 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23892 static basic_json from_cbor(const T* ptr, std::size_t len,
23893 const bool strict = true,
23894 const bool allow_exceptions = true,
23895 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23896 {
23897 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23898 }
23899
23901 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23902 static basic_json from_cbor(detail::span_input_adapter&& i,
23903 const bool strict = true,
23904 const bool allow_exceptions = true,
23905 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23906 {
23907 basic_json result;
23908 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23909 auto ia = i.get();
23910 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23911 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23912 return res ? result : basic_json(value_t::discarded);
23913 }
23914
23917 template<typename InputType>
23919 static basic_json from_msgpack(InputType&& i,
23920 const bool strict = true,
23921 const bool allow_exceptions = true)
23922 {
23923 basic_json result;
23924 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23925 auto ia = detail::input_adapter(std::forward<InputType>(i));
23926 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23927 return res ? result : basic_json(value_t::discarded);
23928 }
23929
23932 template<typename IteratorType>
23934 static basic_json from_msgpack(IteratorType first, IteratorType last,
23935 const bool strict = true,
23936 const bool allow_exceptions = true)
23937 {
23938 basic_json result;
23939 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23940 auto ia = detail::input_adapter(std::move(first), std::move(last));
23941 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23942 return res ? result : basic_json(value_t::discarded);
23943 }
23944
23945 template<typename T>
23947 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23948 static basic_json from_msgpack(const T* ptr, std::size_t len,
23949 const bool strict = true,
23950 const bool allow_exceptions = true)
23951 {
23952 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23953 }
23954
23956 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23957 static basic_json from_msgpack(detail::span_input_adapter&& i,
23958 const bool strict = true,
23959 const bool allow_exceptions = true)
23960 {
23961 basic_json result;
23962 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23963 auto ia = i.get();
23964 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23965 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23966 return res ? result : basic_json(value_t::discarded);
23967 }
23968
23971 template<typename InputType>
23973 static basic_json from_ubjson(InputType&& i,
23974 const bool strict = true,
23975 const bool allow_exceptions = true)
23976 {
23977 basic_json result;
23978 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23979 auto ia = detail::input_adapter(std::forward<InputType>(i));
23980 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23981 return res ? result : basic_json(value_t::discarded);
23982 }
23983
23986 template<typename IteratorType>
23988 static basic_json from_ubjson(IteratorType first, IteratorType last,
23989 const bool strict = true,
23990 const bool allow_exceptions = true)
23991 {
23992 basic_json result;
23993 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23994 auto ia = detail::input_adapter(std::move(first), std::move(last));
23995 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23996 return res ? result : basic_json(value_t::discarded);
23997 }
23998
23999 template<typename T>
24001 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24002 static basic_json from_ubjson(const T* ptr, std::size_t len,
24003 const bool strict = true,
24004 const bool allow_exceptions = true)
24005 {
24006 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24007 }
24008
24010 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24011 static basic_json from_ubjson(detail::span_input_adapter&& i,
24012 const bool strict = true,
24013 const bool allow_exceptions = true)
24014 {
24015 basic_json result;
24016 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24017 auto ia = i.get();
24018 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24019 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
24020 return res ? result : basic_json(value_t::discarded);
24021 }
24022
24025 template<typename InputType>
24027 static basic_json from_bjdata(InputType&& i,
24028 const bool strict = true,
24029 const bool allow_exceptions = true)
24030 {
24031 basic_json result;
24032 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24033 auto ia = detail::input_adapter(std::forward<InputType>(i));
24034 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
24035 return res ? result : basic_json(value_t::discarded);
24036 }
24037
24040 template<typename IteratorType>
24042 static basic_json from_bjdata(IteratorType first, IteratorType last,
24043 const bool strict = true,
24044 const bool allow_exceptions = true)
24045 {
24046 basic_json result;
24047 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24048 auto ia = detail::input_adapter(std::move(first), std::move(last));
24049 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
24050 return res ? result : basic_json(value_t::discarded);
24051 }
24052
24055 template<typename InputType>
24057 static basic_json from_bson(InputType&& i,
24058 const bool strict = true,
24059 const bool allow_exceptions = true)
24060 {
24061 basic_json result;
24062 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24063 auto ia = detail::input_adapter(std::forward<InputType>(i));
24064 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
24065 return res ? result : basic_json(value_t::discarded);
24066 }
24067
24070 template<typename IteratorType>
24072 static basic_json from_bson(IteratorType first, IteratorType last,
24073 const bool strict = true,
24074 const bool allow_exceptions = true)
24075 {
24076 basic_json result;
24077 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24078 auto ia = detail::input_adapter(std::move(first), std::move(last));
24079 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
24080 return res ? result : basic_json(value_t::discarded);
24081 }
24082
24083 template<typename T>
24085 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24086 static basic_json from_bson(const T* ptr, std::size_t len,
24087 const bool strict = true,
24088 const bool allow_exceptions = true)
24089 {
24090 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24091 }
24092
24094 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24095 static basic_json from_bson(detail::span_input_adapter&& i,
24096 const bool strict = true,
24097 const bool allow_exceptions = true)
24098 {
24099 basic_json result;
24100 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24101 auto ia = i.get();
24102 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24103 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
24104 return res ? result : basic_json(value_t::discarded);
24105 }
24107
24109 // JSON Pointer support //
24111
24114
24118 {
24119 return ptr.get_unchecked(this);
24120 }
24121
24122 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24123 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24124 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24125 {
24126 return ptr.get_unchecked(this);
24127 }
24128
24132 {
24133 return ptr.get_unchecked(this);
24134 }
24135
24136 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24137 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24138 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24139 {
24140 return ptr.get_unchecked(this);
24141 }
24142
24146 {
24147 return ptr.get_checked(this);
24148 }
24149
24150 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24151 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24152 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24153 {
24154 return ptr.get_checked(this);
24155 }
24156
24160 {
24161 return ptr.get_checked(this);
24162 }
24163
24164 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24165 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24166 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24167 {
24168 return ptr.get_checked(this);
24169 }
24170
24174 {
24175 basic_json result(value_t::object);
24176 json_pointer::flatten("", *this, result);
24177 return result;
24178 }
24179
24183 {
24184 return json_pointer::unflatten(*this);
24185 }
24186
24188
24190 // JSON Patch functions //
24192
24195
24198 void patch_inplace(const basic_json& json_patch)
24199 {
24200 basic_json& result = *this;
24201 // the valid JSON Patch operations
24202 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24203
24204 const auto get_op = [](const std::string & op)
24205 {
24206 if (op == "add")
24207 {
24208 return patch_operations::add;
24209 }
24210 if (op == "remove")
24211 {
24212 return patch_operations::remove;
24213 }
24214 if (op == "replace")
24215 {
24216 return patch_operations::replace;
24217 }
24218 if (op == "move")
24219 {
24220 return patch_operations::move;
24221 }
24222 if (op == "copy")
24223 {
24224 return patch_operations::copy;
24225 }
24226 if (op == "test")
24227 {
24228 return patch_operations::test;
24229 }
24230
24231 return patch_operations::invalid;
24232 };
24233
24234 // wrapper for "add" operation; add value at ptr
24235 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24236 {
24237 // adding to the root of the target document means replacing it
24238 if (ptr.empty())
24239 {
24240 result = val;
24241 return;
24242 }
24243
24244 // make sure the top element of the pointer exists
24245 json_pointer const top_pointer = ptr.top();
24246 if (top_pointer != ptr)
24247 {
24248 result.at(top_pointer);
24249 }
24250
24251 // get reference to parent of JSON pointer ptr
24252 const auto last_path = ptr.back();
24253 ptr.pop_back();
24254 // parent must exist when performing patch add per RFC6902 specs
24255 basic_json& parent = result.at(ptr);
24256
24257 switch (parent.m_data.m_type)
24258 {
24259 case value_t::null:
24260 case value_t::object:
24261 {
24262 // use operator[] to add value
24263 parent[last_path] = val;
24264 break;
24265 }
24266
24267 case value_t::array:
24268 {
24269 if (last_path == "-")
24270 {
24271 // special case: append to back
24272 parent.push_back(val);
24273 }
24274 else
24275 {
24276 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24277 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24278 {
24279 // avoid undefined behavior
24280 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24281 }
24282
24283 // default case: insert add offset
24284 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24285 }
24286 break;
24287 }
24288
24289 // if there exists a parent it cannot be primitive
24290 case value_t::string: // LCOV_EXCL_LINE
24291 case value_t::boolean: // LCOV_EXCL_LINE
24292 case value_t::number_integer: // LCOV_EXCL_LINE
24293 case value_t::number_unsigned: // LCOV_EXCL_LINE
24294 case value_t::number_float: // LCOV_EXCL_LINE
24295 case value_t::binary: // LCOV_EXCL_LINE
24296 case value_t::discarded: // LCOV_EXCL_LINE
24297 default: // LCOV_EXCL_LINE
24298 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24299 }
24300 };
24301
24302 // wrapper for "remove" operation; remove value at ptr
24303 const auto operation_remove = [this, & result](json_pointer & ptr)
24304 {
24305 // get reference to parent of JSON pointer ptr
24306 const auto last_path = ptr.back();
24307 ptr.pop_back();
24308 basic_json& parent = result.at(ptr);
24309
24310 // remove child
24311 if (parent.is_object())
24312 {
24313 // perform range check
24314 auto it = parent.find(last_path);
24315 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24316 {
24317 parent.erase(it);
24318 }
24319 else
24320 {
24321 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24322 }
24323 }
24324 else if (parent.is_array())
24325 {
24326 // note erase performs range check
24327 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24328 }
24329 };
24330
24331 // type check: top level value must be an array
24332 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24333 {
24334 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24335 }
24336
24337 // iterate and apply the operations
24338 for (const auto& val : json_patch)
24339 {
24340 // wrapper to get a value for an operation
24341 const auto get_value = [&val](const std::string & op,
24342 const std::string & member,
24343 bool string_type) -> basic_json &
24344 {
24345 // find value
24346 auto it = val.m_data.m_value.object->find(member);
24347
24348 // context-sensitive error message
24349 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24350
24351 // check if desired value is present
24352 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24353 {
24354 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24355 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24356 }
24357
24358 // check if result is of type string
24359 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24360 {
24361 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24362 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24363 }
24364
24365 // no error: return value
24366 return it->second;
24367 };
24368
24369 // type check: every element of the array must be an object
24370 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24371 {
24372 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24373 }
24374
24375 // collect mandatory members
24376 const auto op = get_value("op", "op", true).template get<std::string>();
24377 const auto path = get_value(op, "path", true).template get<std::string>();
24378 json_pointer ptr(path);
24379
24380 switch (get_op(op))
24381 {
24382 case patch_operations::add:
24383 {
24384 operation_add(ptr, get_value("add", "value", false));
24385 break;
24386 }
24387
24388 case patch_operations::remove:
24389 {
24390 operation_remove(ptr);
24391 break;
24392 }
24393
24394 case patch_operations::replace:
24395 {
24396 // the "path" location must exist - use at()
24397 result.at(ptr) = get_value("replace", "value", false);
24398 break;
24399 }
24400
24401 case patch_operations::move:
24402 {
24403 const auto from_path = get_value("move", "from", true).template get<std::string>();
24404 json_pointer from_ptr(from_path);
24405
24406 // the "from" location must exist - use at()
24407 basic_json const v = result.at(from_ptr);
24408
24409 // The move operation is functionally identical to a
24410 // "remove" operation on the "from" location, followed
24411 // immediately by an "add" operation at the target
24412 // location with the value that was just removed.
24413 operation_remove(from_ptr);
24414 operation_add(ptr, v);
24415 break;
24416 }
24417
24418 case patch_operations::copy:
24419 {
24420 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24421 const json_pointer from_ptr(from_path);
24422
24423 // the "from" location must exist - use at()
24424 basic_json const v = result.at(from_ptr);
24425
24426 // The copy is functionally identical to an "add"
24427 // operation at the target location using the value
24428 // specified in the "from" member.
24429 operation_add(ptr, v);
24430 break;
24431 }
24432
24433 case patch_operations::test:
24434 {
24435 bool success = false;
24436 JSON_TRY
24437 {
24438 // check if "value" matches the one at "path"
24439 // the "path" location must exist - use at()
24440 success = (result.at(ptr) == get_value("test", "value", false));
24441 }
24443 {
24444 // ignore out of range errors: success remains false
24445 }
24446
24447 // throw an exception if test fails
24448 if (JSON_HEDLEY_UNLIKELY(!success))
24449 {
24450 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24451 }
24452
24453 break;
24454 }
24455
24456 case patch_operations::invalid:
24457 default:
24458 {
24459 // op must be "add", "remove", "replace", "move", "copy", or
24460 // "test"
24461 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24462 }
24463 }
24464 }
24465 }
24466
24469 basic_json patch(const basic_json& json_patch) const
24470 {
24471 basic_json result = *this;
24472 result.patch_inplace(json_patch);
24473 return result;
24474 }
24475
24479 static basic_json diff(const basic_json& source, const basic_json& target,
24480 const std::string& path = "")
24481 {
24482 // the patch
24483 basic_json result(value_t::array);
24484
24485 // if the values are the same, return empty patch
24486 if (source == target)
24487 {
24488 return result;
24489 }
24490
24491 if (source.type() != target.type())
24492 {
24493 // different types: replace value
24494 result.push_back(
24495 {
24496 {"op", "replace"}, {"path", path}, {"value", target}
24497 });
24498 return result;
24499 }
24500
24501 switch (source.type())
24502 {
24503 case value_t::array:
24504 {
24505 // first pass: traverse common elements
24506 std::size_t i = 0;
24507 while (i < source.size() && i < target.size())
24508 {
24509 // recursive call to compare array values at index i
24510 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24511 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24512 ++i;
24513 }
24514
24515 // We now reached the end of at least one array
24516 // in a second pass, traverse the remaining elements
24517
24518 // remove my remaining elements
24519 const auto end_index = static_cast<difference_type>(result.size());
24520 while (i < source.size())
24521 {
24522 // add operations in reverse order to avoid invalid
24523 // indices
24524 result.insert(result.begin() + end_index, object(
24525 {
24526 {"op", "remove"},
24527 {"path", detail::concat(path, '/', std::to_string(i))}
24528 }));
24529 ++i;
24530 }
24531
24532 // add other remaining elements
24533 while (i < target.size())
24534 {
24535 result.push_back(
24536 {
24537 {"op", "add"},
24538 {"path", detail::concat(path, "/-")},
24539 {"value", target[i]}
24540 });
24541 ++i;
24542 }
24543
24544 break;
24545 }
24546
24547 case value_t::object:
24548 {
24549 // first pass: traverse this object's elements
24550 for (auto it = source.cbegin(); it != source.cend(); ++it)
24551 {
24552 // escape the key name to be used in a JSON patch
24553 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24554
24555 if (target.find(it.key()) != target.end())
24556 {
24557 // recursive call to compare object values at key it
24558 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24559 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24560 }
24561 else
24562 {
24563 // found a key that is not in o -> remove it
24564 result.push_back(object(
24565 {
24566 {"op", "remove"}, {"path", path_key}
24567 }));
24568 }
24569 }
24570
24571 // second pass: traverse other object's elements
24572 for (auto it = target.cbegin(); it != target.cend(); ++it)
24573 {
24574 if (source.find(it.key()) == source.end())
24575 {
24576 // found a key that is not in this -> add it
24577 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24578 result.push_back(
24579 {
24580 {"op", "add"}, {"path", path_key},
24581 {"value", it.value()}
24582 });
24583 }
24584 }
24585
24586 break;
24587 }
24588
24589 case value_t::null:
24590 case value_t::string:
24591 case value_t::boolean:
24592 case value_t::number_integer:
24593 case value_t::number_unsigned:
24594 case value_t::number_float:
24595 case value_t::binary:
24596 case value_t::discarded:
24597 default:
24598 {
24599 // both primitive type: replace value
24600 result.push_back(
24601 {
24602 {"op", "replace"}, {"path", path}, {"value", target}
24603 });
24604 break;
24605 }
24606 }
24607
24608 return result;
24609 }
24611
24613 // JSON Merge Patch functions //
24615
24618
24621 void merge_patch(const basic_json& apply_patch)
24622 {
24623 if (apply_patch.is_object())
24624 {
24625 if (!is_object())
24626 {
24627 *this = object();
24628 }
24629 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24630 {
24631 if (it.value().is_null())
24632 {
24633 erase(it.key());
24634 }
24635 else
24636 {
24637 operator[](it.key()).merge_patch(it.value());
24638 }
24639 }
24640 }
24641 else
24642 {
24643 *this = apply_patch;
24644 }
24645 }
24646
24648};
24649
24654{
24655 return j.dump();
24656}
24657
24658inline namespace literals
24659{
24660inline namespace json_literals
24661{
24662
24666#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24667 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24668#else
24669 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24670#endif
24671{
24672 return nlohmann::json::parse(s, s + n);
24673}
24674
24678#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24679 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24680#else
24681 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24682#endif
24683{
24684 return nlohmann::json::json_pointer(std::string(s, n));
24685}
24686
24687} // namespace json_literals
24688} // namespace literals
24690
24692// nonmember support //
24694
24695namespace std // NOLINT(cert-dcl58-cpp)
24696{
24697
24701struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24702{
24703 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24704 {
24705 return nlohmann::detail::hash(j);
24706 }
24707};
24708
24709// specialization for std::less<value_t>
24710template<>
24711struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24712{
24717 bool operator()(::nlohmann::detail::value_t lhs,
24718 ::nlohmann::detail::value_t rhs) const noexcept
24719 {
24720#if JSON_HAS_THREE_WAY_COMPARISON
24721 return std::is_lt(lhs <=> rhs); // *NOPAD*
24722#else
24723 return ::nlohmann::detail::operator<(lhs, rhs);
24724#endif
24725 }
24726};
24727
24728// C++20 prohibit function specialization in the std namespace.
24729#ifndef JSON_HAS_CPP_20
24730
24734inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24735 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24736 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24737{
24738 j1.swap(j2);
24739}
24740
24741#endif
24742
24743} // namespace std
24744
24745#if JSON_USE_GLOBAL_UDLS
24746 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24747 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24748 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24749 #else
24750 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24751 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24752 #endif
24753#endif
24754
24755// #include <nlohmann/detail/macro_unscope.hpp>
24756// __ _____ _____ _____
24757// __| | __| | | | JSON for Modern C++
24758// | | |__ | | | | | | version 3.11.3
24759// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24760//
24761// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
24762// SPDX-License-Identifier: MIT
24763
24764
24765
24766// restore clang diagnostic settings
24767#if defined(__clang__)
24768 #pragma clang diagnostic pop
24769#endif
24770
24771// clean up
24772#undef JSON_ASSERT
24773#undef JSON_INTERNAL_CATCH
24774#undef JSON_THROW
24775#undef JSON_PRIVATE_UNLESS_TESTED
24776#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24777#undef NLOHMANN_BASIC_JSON_TPL
24778#undef JSON_EXPLICIT
24779#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24780#undef JSON_INLINE_VARIABLE
24781#undef JSON_NO_UNIQUE_ADDRESS
24782#undef JSON_DISABLE_ENUM_SERIALIZATION
24783#undef JSON_USE_GLOBAL_UDLS
24784
24785#ifndef JSON_TEST_KEEP_MACROS
24786 #undef JSON_CATCH
24787 #undef JSON_TRY
24788 #undef JSON_HAS_CPP_11
24789 #undef JSON_HAS_CPP_14
24790 #undef JSON_HAS_CPP_17
24791 #undef JSON_HAS_CPP_20
24792 #undef JSON_HAS_FILESYSTEM
24793 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24794 #undef JSON_HAS_THREE_WAY_COMPARISON
24795 #undef JSON_HAS_RANGES
24796 #undef JSON_HAS_STATIC_RTTI
24797 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24798#endif
24799
24800// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24801// __ _____ _____ _____
24802// __| | __| | | | JSON for Modern C++
24803// | | |__ | | | | | | version 3.11.3
24804// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24805//
24806// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
24807// SPDX-License-Identifier: MIT
24808
24809
24810
24811#undef JSON_HEDLEY_ALWAYS_INLINE
24812#undef JSON_HEDLEY_ARM_VERSION
24813#undef JSON_HEDLEY_ARM_VERSION_CHECK
24814#undef JSON_HEDLEY_ARRAY_PARAM
24815#undef JSON_HEDLEY_ASSUME
24816#undef JSON_HEDLEY_BEGIN_C_DECLS
24817#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24818#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24819#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24820#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24821#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24822#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24823#undef JSON_HEDLEY_CLANG_HAS_WARNING
24824#undef JSON_HEDLEY_COMPCERT_VERSION
24825#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24826#undef JSON_HEDLEY_CONCAT
24827#undef JSON_HEDLEY_CONCAT3
24828#undef JSON_HEDLEY_CONCAT3_EX
24829#undef JSON_HEDLEY_CONCAT_EX
24830#undef JSON_HEDLEY_CONST
24831#undef JSON_HEDLEY_CONSTEXPR
24832#undef JSON_HEDLEY_CONST_CAST
24833#undef JSON_HEDLEY_CPP_CAST
24834#undef JSON_HEDLEY_CRAY_VERSION
24835#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24836#undef JSON_HEDLEY_C_DECL
24837#undef JSON_HEDLEY_DEPRECATED
24838#undef JSON_HEDLEY_DEPRECATED_FOR
24839#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24840#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24841#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24842#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24843#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24844#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24845#undef JSON_HEDLEY_DIAGNOSTIC_POP
24846#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24847#undef JSON_HEDLEY_DMC_VERSION
24848#undef JSON_HEDLEY_DMC_VERSION_CHECK
24849#undef JSON_HEDLEY_EMPTY_BASES
24850#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24851#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24852#undef JSON_HEDLEY_END_C_DECLS
24853#undef JSON_HEDLEY_FLAGS
24854#undef JSON_HEDLEY_FLAGS_CAST
24855#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24856#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24857#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24858#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24859#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24860#undef JSON_HEDLEY_GCC_HAS_FEATURE
24861#undef JSON_HEDLEY_GCC_HAS_WARNING
24862#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24863#undef JSON_HEDLEY_GCC_VERSION
24864#undef JSON_HEDLEY_GCC_VERSION_CHECK
24865#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24866#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24867#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24868#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24869#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24870#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24871#undef JSON_HEDLEY_GNUC_HAS_WARNING
24872#undef JSON_HEDLEY_GNUC_VERSION
24873#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24874#undef JSON_HEDLEY_HAS_ATTRIBUTE
24875#undef JSON_HEDLEY_HAS_BUILTIN
24876#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24877#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24878#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24879#undef JSON_HEDLEY_HAS_EXTENSION
24880#undef JSON_HEDLEY_HAS_FEATURE
24881#undef JSON_HEDLEY_HAS_WARNING
24882#undef JSON_HEDLEY_IAR_VERSION
24883#undef JSON_HEDLEY_IAR_VERSION_CHECK
24884#undef JSON_HEDLEY_IBM_VERSION
24885#undef JSON_HEDLEY_IBM_VERSION_CHECK
24886#undef JSON_HEDLEY_IMPORT
24887#undef JSON_HEDLEY_INLINE
24888#undef JSON_HEDLEY_INTEL_CL_VERSION
24889#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24890#undef JSON_HEDLEY_INTEL_VERSION
24891#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24892#undef JSON_HEDLEY_IS_CONSTANT
24893#undef JSON_HEDLEY_IS_CONSTEXPR_
24894#undef JSON_HEDLEY_LIKELY
24895#undef JSON_HEDLEY_MALLOC
24896#undef JSON_HEDLEY_MCST_LCC_VERSION
24897#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24898#undef JSON_HEDLEY_MESSAGE
24899#undef JSON_HEDLEY_MSVC_VERSION
24900#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24901#undef JSON_HEDLEY_NEVER_INLINE
24902#undef JSON_HEDLEY_NON_NULL
24903#undef JSON_HEDLEY_NO_ESCAPE
24904#undef JSON_HEDLEY_NO_RETURN
24905#undef JSON_HEDLEY_NO_THROW
24906#undef JSON_HEDLEY_NULL
24907#undef JSON_HEDLEY_PELLES_VERSION
24908#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24909#undef JSON_HEDLEY_PGI_VERSION
24910#undef JSON_HEDLEY_PGI_VERSION_CHECK
24911#undef JSON_HEDLEY_PREDICT
24912#undef JSON_HEDLEY_PRINTF_FORMAT
24913#undef JSON_HEDLEY_PRIVATE
24914#undef JSON_HEDLEY_PUBLIC
24915#undef JSON_HEDLEY_PURE
24916#undef JSON_HEDLEY_REINTERPRET_CAST
24917#undef JSON_HEDLEY_REQUIRE
24918#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24919#undef JSON_HEDLEY_REQUIRE_MSG
24920#undef JSON_HEDLEY_RESTRICT
24921#undef JSON_HEDLEY_RETURNS_NON_NULL
24922#undef JSON_HEDLEY_SENTINEL
24923#undef JSON_HEDLEY_STATIC_ASSERT
24924#undef JSON_HEDLEY_STATIC_CAST
24925#undef JSON_HEDLEY_STRINGIFY
24926#undef JSON_HEDLEY_STRINGIFY_EX
24927#undef JSON_HEDLEY_SUNPRO_VERSION
24928#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24929#undef JSON_HEDLEY_TINYC_VERSION
24930#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24931#undef JSON_HEDLEY_TI_ARMCL_VERSION
24932#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24933#undef JSON_HEDLEY_TI_CL2000_VERSION
24934#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24935#undef JSON_HEDLEY_TI_CL430_VERSION
24936#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24937#undef JSON_HEDLEY_TI_CL6X_VERSION
24938#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24939#undef JSON_HEDLEY_TI_CL7X_VERSION
24940#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24941#undef JSON_HEDLEY_TI_CLPRU_VERSION
24942#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24943#undef JSON_HEDLEY_TI_VERSION
24944#undef JSON_HEDLEY_TI_VERSION_CHECK
24945#undef JSON_HEDLEY_UNAVAILABLE
24946#undef JSON_HEDLEY_UNLIKELY
24947#undef JSON_HEDLEY_UNPREDICTABLE
24948#undef JSON_HEDLEY_UNREACHABLE
24949#undef JSON_HEDLEY_UNREACHABLE_RETURN
24950#undef JSON_HEDLEY_VERSION
24951#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24952#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24953#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24954#undef JSON_HEDLEY_VERSION_ENCODE
24955#undef JSON_HEDLEY_WARNING
24956#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24957#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24958#undef JSON_HEDLEY_FALL_THROUGH
24959
24960
24961
24962#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:19598
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:20870
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22103
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:21671
size_type size() const noexcept
returns the number of elements
Definition json.hpp:22444
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:23877
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23809
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.hpp:21243
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22301
reference back()
access the last element
Definition json.hpp:21907
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.hpp:20334
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22317
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:24469
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:23657
const_reference front() const
access the first element
Definition json.hpp:21900
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:20863
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22961
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21851
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22220
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.hpp:19729
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23828
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:19673
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:20835
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:19733
data(size_type cnt, const basic_json &val)
Definition json.hpp:23701
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24072
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23820
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24117
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:19724
std::size_t size_type
a type to represent container sizes
Definition json.hpp:19716
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:20807
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:21695
const value_type & const_reference
the type of an element const reference
Definition json.hpp:19711
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23038
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:21333
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:22483
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:22907
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21344
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:20884
JSON_PRIVATE_UNLESS_TESTED const_reference rhs
Definition json.hpp:23156
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:22699
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:22587
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:21640
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22389
const_reference back() const
access the last element
Definition json.hpp:21916
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:21998
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:22644
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22978
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:23973
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:20471
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:22811
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24057
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:19739
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:19864
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:21503
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:22292
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:20842
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:22914
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:23836
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22324
data m_data
Definition json.hpp:23719
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:22683
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:20301
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:20512
ValueType & get_to(ValueType &v) const
Definition json.hpp:21310
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23775
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:22267
JSON_PRIVATE_UNLESS_TESTED const_reference bool inverse
Definition json.hpp:23156
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:21750
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22308
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24027
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24159
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:20482
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20322
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:23861
basic_json flatten() const
return flattened JSON value
Definition json.hpp:24173
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:23988
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22114
const binary_t & get_binary() const
get a binary value
Definition json.hpp:21415
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:22831
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24198
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21803
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition json.hpp:24479
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24131
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:19840
value_type & reference
the type of an element reference
Definition json.hpp:19709
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22237
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:23745
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.hpp:23852
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.hpp:22150
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:20460
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:21541
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:19747
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:20519
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22164
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:23736
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:21928
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:22784
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:19860
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21725
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:19719
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:19722
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:20771
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:24621
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:21297
reference operator[](T *key)
Definition json.hpp:21656
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:21437
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22180
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:20849
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22331
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23782
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24145
BooleanType boolean_t
a type for a boolean
Definition json.hpp:19848
detail::value_t value_t
Definition json.hpp:19663
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition json.hpp:19827
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22675
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:22283
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:21618
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21055
~basic_json() noexcept
destructor
Definition json.hpp:20753
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:22352
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:20401
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23054
binary_t & get_binary()
get a binary value
Definition json.hpp:21403
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22276
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:20828
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:22882
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:23919
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21284
const_reference operator[](T *key) const
Definition json.hpp:21662
data(const value_t v)
Definition json.hpp:23696
reference operator[](size_type idx)
access specified array element
Definition json.hpp:21559
basic_json(const JsonRef &ref)
Definition json.hpp:20640
JSONSerializer< T, SFINAE > json_serializer
Definition json.hpp:19667
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:20730
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition json.hpp:22364
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23801
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:21321
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:19852
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21044
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:21521
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:20877
void swap(object_t &other)
exchanges the values
Definition json.hpp:23006
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:24182
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:22862
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:20493
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22382
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:22405
void swap(array_t &other)
exchanges the values
Definition json.hpp:22990
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22121
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:22612
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22244
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:20793
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:22708
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21826
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:20504
data() noexcept=default
StringType string_t
a type for a string
Definition json.hpp:19844
friend class ::nlohmann::detail::parser
Definition json.hpp:19608
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.hpp:19836
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:22620
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21776
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:21483
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24042
json_value m_value
the value of the current element
Definition json.hpp:23694
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:22345
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:20821
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22210
reference front()
access the first element
Definition json.hpp:21893
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:20800
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:20814
void clear() noexcept
clears the contents
Definition json.hpp:22526
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23793
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false)
Definition json.hpp:23581
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:20713
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:19727
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20314
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:21605
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:19714
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:22804
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22338
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:19856
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:23642
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23759
void swap(string_t &other)
exchanges the values
Definition json.hpp:23022
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20348
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:19731
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:21460
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.hpp:19868
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:20644
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22652
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:22733
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:23752
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:20856
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23768
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:23934
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:22765
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:20531
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition json.hpp:23635
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22228
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.hpp:23845
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22196
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:19665
an internal type for a backed binary type
Definition json.hpp:5979
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:6019
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:5985
std::uint64_t subtype_type
Definition json.hpp:5982
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:6013
BinaryType container_type
Definition json.hpp:5981
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6007
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5995
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6034
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6000
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6041
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:5990
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6026
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6048
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9368
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9384
binary_reader & operator=(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:9405
binary_reader & operator=(binary_reader &&)=default
general exception of the basic_json class
Definition json.hpp:4418
const int id
the id of the exception
Definition json.hpp:4427
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4438
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4433
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4421
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4444
exception indicating errors with iterators
Definition json.hpp:4569
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4572
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:13104
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:13687
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13241
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:13632
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13231
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:13574
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:13614
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:13678
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:13484
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:13787
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:13525
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13422
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:13641
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13749
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:13134
pointer operator->() const
dereference the iterator
Definition json.hpp:13380
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.hpp:13812
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:13720
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:13129
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:13698
reference value() const
return the value of an iterator
Definition json.hpp:13803
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:13623
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.hpp:13138
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:13433
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:13132
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13336
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13709
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13216
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:13565
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:13473
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.hpp:13143
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13206
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13297
Definition json.hpp:5257
iteration_proxy_value operator++(int) &
Definition json.hpp:5313
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5322
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5328
std::ptrdiff_t difference_type
Definition json.hpp:5259
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.hpp:5280
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5305
std::forward_iterator_tag iterator_category
Definition json.hpp:5263
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5370
const string_type & key() const
return key of the iterator
Definition json.hpp:5334
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5264
proxy class for the items() function
Definition json.hpp:5378
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5403
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5397
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5387
iteration_proxy & operator=(iteration_proxy const &)=default
Definition json.hpp:15017
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:15025
json_ref(value_type &&value)
Definition json.hpp:15021
value_type const & operator*() const
Definition json.hpp:15056
value_type const * operator->() const
Definition json.hpp:15061
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:15029
json_ref(Args &&... args)
Definition json.hpp:15036
value_type moved_or_copied() const
Definition json.hpp:15047
BasicJsonType value_type
Definition json.hpp:15019
a template for a reverse iterator class
Definition json.hpp:13866
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:13882
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:13894
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:13888
std::ptrdiff_t difference_type
Definition json.hpp:13868
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:13906
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13930
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:13936
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:13924
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:13872
reference value() const
return the value of an iterator
Definition json.hpp:13943
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:13879
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:13900
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:13870
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13918
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:13875
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:13912
Definition json.hpp:7436
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7439
bool end_object()
Definition json.hpp:7489
bool start_object(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:7479
bool binary(binary_t &)
Definition json.hpp:7474
bool number_integer(number_integer_t)
Definition json.hpp:7454
bool start_array(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:7494
bool boolean(bool)
Definition json.hpp:7449
bool null()
Definition json.hpp:7444
bool end_array()
Definition json.hpp:7499
bool number_unsigned(number_unsigned_t)
Definition json.hpp:7459
bool string(string_t &)
Definition json.hpp:7469
typename BasicJsonType::binary_t binary_t
Definition json.hpp:7442
bool number_float(number_float_t, const string_t &)
Definition json.hpp:7464
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:7504
bool key(string_t &)
Definition json.hpp:7484
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7438
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7440
typename BasicJsonType::string_t string_t
Definition json.hpp:7441
Definition json.hpp:7129
bool boolean(bool val)
Definition json.hpp:7160
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:7317
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true)
Definition json.hpp:7139
typename BasicJsonType::string_t string_t
Definition json.hpp:7134
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:7178
constexpr bool is_errored() const
Definition json.hpp:7329
bool string(string_t &val)
Definition json.hpp:7184
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7132
typename BasicJsonType::binary_t binary_t
Definition json.hpp:7135
bool start_object(std::size_t len)
Definition json.hpp:7196
bool start_array(std::size_t len)
Definition json.hpp:7267
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7131
bool end_array()
Definition json.hpp:7284
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
bool key(string_t &val)
Definition json.hpp:7214
bool end_object()
Definition json.hpp:7231
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:7137
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:7136
bool null()
Definition json.hpp:7154
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:7172
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7133
bool number_integer(number_integer_t val)
Definition json.hpp:7166
bool binary(binary_t &val)
Definition json.hpp:7190
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:6946
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool string(string_t &val)
Definition json.hpp:7000
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:6959
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:7067
bool null()
Definition json.hpp:6970
typename BasicJsonType::string_t string_t
Definition json.hpp:6951
bool start_object(std::size_t len)
Definition json.hpp:7012
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6949
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:6988
bool number_integer(number_integer_t val)
Definition json.hpp:6982
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6948
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.hpp:7006
json_sax_dom_parser(json_sax_dom_parser &&)=default
bool boolean(bool val)
Definition json.hpp:6976
bool end_array()
Definition json.hpp:7056
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:6994
bool end_object()
Definition json.hpp:7034
constexpr bool is_errored() const
Definition json.hpp:7079
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6952
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6950
bool start_array(std::size_t len)
Definition json.hpp:7044
bool key(string_t &val)
Definition json.hpp:7024
Definition json.hpp:7553
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7580
token_type
token types for the parser
Definition json.hpp:7557
lexical analysis
Definition json.hpp:7630
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:9012
void skip_whitespace()
Definition json.hpp:9026
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7641
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8999
std::string get_token_string() const
Definition json.hpp:8974
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8933
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8966
token_type scan()
Definition json.hpp:9035
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8939
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7639
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8951
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8945
exception indicating other library errors
Definition json.hpp:4621
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4624
exception indicating access out of the defined range
Definition json.hpp:4604
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4607
exception indicating a parse error
Definition json.hpp:4516
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.hpp:4528
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4536
const std::size_t byte
byte index of the parse error
Definition json.hpp:4553
Definition json.hpp:18257
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:19181
std::uint8_t state
Definition json.hpp:18599
std::size_t bytes_after_last_accept
Definition json.hpp:18603
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18272
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition json.hpp:18597
std::size_t undumped_chars
Definition json.hpp:18604
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:19176
const char decimal_point
the locale's decimal point character
Definition json.hpp:19178
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19189
string_t indent_string
the indentation string
Definition json.hpp:19186
const std::lconv * loc
the locale
Definition json.hpp:19174
serializer & operator=(serializer &&)=delete
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:19171
const char indent_char
the indentation character
Definition json.hpp:19184
std::size_t bytes
Definition json.hpp:18600
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:18312
serializer(const serializer &)=delete
serializer(serializer &&)=delete
exception indicating executing a member function with a wrong type
Definition json.hpp:4587
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4590
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:14038
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.hpp:14133
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:14060
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.hpp:14140
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14064
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14199
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
Definition json.hpp:14933
void pop_back()
remove last reference token
Definition json.hpp:14161
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14070
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14118
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14192
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14100
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.hpp:14125
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14147
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
Definition json.hpp:14958
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14110
friend class json_pointer
Definition json.hpp:14044
const string_t & back() const
return last reference token
Definition json.hpp:14173
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14091
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14185
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
Definition json.hpp:14983
decltype(get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5451
GLint ref
Definition glad.h:958
const GLdouble * v
Definition glad.h:1378
GLubyte GLubyte GLubyte GLubyte w
Definition glad.h:1438
GLboolean * data
Definition glad.h:979
GLuint GLsizei GLsizei * length
Definition glad.h:1252
GLint GLint GLsizei GLint GLenum format
Definition glad.h:910
GLuint GLuint end
Definition glad.h:1068
GLuint index
Definition glad.h:1225
GLuint const GLchar * name
Definition glad.h:1225
GLint GLsizei count
Definition glad.h:1025
GLint GLint GLsizei GLint GLenum GLenum type
Definition glad.h:910
GLint y
Definition glad.h:895
GLboolean GLboolean GLboolean b
Definition glad.h:1512
GLsizei GLsizei GLchar * source
Definition glad.h:1276
GLsizeiptr size
Definition glad.h:1182
GLuint buffer
Definition glad.h:1170
GLint GLenum GLint x
Definition glad.h:1034
GLsizei const GLfloat * value
Definition glad.h:1339
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean r
Definition glad.h:1512
GLuint start
Definition glad.h:1068
GLsizei const GLchar *const * string
Definition glad.h:1309
GLboolean GLboolean GLboolean GLboolean a
Definition glad.h:1512
GLint first
Definition glad.h:1025
GLintptr offset
Definition glad.h:1185
GLdouble f
Definition glad.h:1015
GLM_FUNC_QUALIFIER vec< L, T, Q > exp(vec< L, T, Q > const &x)
Definition func_exponential.inl:80
GLM_FUNC_DECL GLM_CONSTEXPR genType e()
Definition constants.inl:108
uint64 uint64_t
Definition fwd.hpp:145
int64 int64_t
Definition fwd.hpp:85
uint32 uint32_t
Definition fwd.hpp:131
uint8 uint8_t
Definition fwd.hpp:103
uint16 uint16_t
Definition fwd.hpp:117
genType::value_type const * begin(genType const &v)
Definition range.hpp:68
detail::uint8 byte
Definition raw_data.hpp:32
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2604
#define JSON_HEDLEY_CONST
Definition json.hpp:1822
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1106
#define JSON_INLINE_VARIABLE
Definition json.hpp:2503
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1452
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2563
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1717
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1610
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2530
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:24653
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2051
#define JSON_CATCH(exception)
Definition json.hpp:2529
#define JSON_ASSERT(x)
Definition json.hpp:2556
#define JSON_THROW(exception)
Definition json.hpp:2527
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:77
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2614
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1718
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:12307
#define JSON_TRY
Definition json.hpp:2528
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:144
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2509
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2820
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:134
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12304
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1107
#define JSON_EXPLICIT
Definition json.hpp:2857
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1400
#define JSON_HEDLEY_PURE
Definition json.hpp:1791
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:14983
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:23079
constexpr bool is_transparent()
Definition json.hpp:4228
constexpr bool is_c_string()
Definition json.hpp:4200
detail namespace with internal helper functions
Definition json.hpp:253
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:5868
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:313
typename make_void< Ts... >::type void_t
Definition json.hpp:259
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4309
OutStringType concat(Args &&... args)
Definition json.hpp:4383
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4318
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3551
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3256
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3557
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.hpp:4050
typename T::pointer pointer_t
Definition json.hpp:3542
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4312
integer_sequence< size_t, Ints... > index_sequence
Definition json.hpp:3171
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3217
typename T::value_type value_type_t
Definition json.hpp:3536
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:317
T conditional_static_cast(U value)
Definition json.hpp:4084
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4324
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3129
typename T::mapped_type mapped_type_t
Definition json.hpp:3530
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3005
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3778
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5413
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9341
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:310
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3554
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3225
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4190
void concat_into(OutStringType &)
Definition json.hpp:4299
typename T::key_type key_type_t
Definition json.hpp:3533
constexpr bool value_in_range_of(T val)
Definition json.hpp:4184
value_t
the JSON type enumeration
Definition json.hpp:2907
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4107
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:304
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.hpp:4034
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4315
typename T::iterator_category iterator_category_t
Definition json.hpp:3548
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:2936
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.hpp:4062
error_handler_t
how to treat decoding errors
Definition json.hpp:18249
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
std::size_t concat_length()
Definition json.hpp:4268
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3781
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3630
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4303
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:5729
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3233
typename T::difference_type difference_type_t
Definition json.hpp:3539
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3115
typename T::is_transparent detect_is_transparent
Definition json.hpp:4020
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:13992
typename T::reference reference_t
Definition json.hpp:3545
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:4053
typename T::key_compare detect_key_compare
Definition json.hpp:3614
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4321
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:298
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3024
void int_to_string(string_type &target, std::size_t value)
Definition json.hpp:5250
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.hpp:4112
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4306
GLM_FUNC_QUALIFIER vec< 3, T, Q > combine(vec< 3, T, Q > const &a, vec< 3, T, Q > const &b, T ascl, T bscl)
Make a linear combination of two vectors and return the result.
Definition matrix_decompose.inl:13
GLM_FUNC_DECL GLM_CONSTEXPR mat< 2, 2, T, Q > operator-(mat< 2, 2, T, Q > const &m)
Definition type_mat2x2.inl:355
GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat< 2, 2, T, Q > const &m1, mat< 2, 2, T, Q > const &m2)
Definition type_mat2x2.inl:526
GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat< 2, 2, T, Q > const &m1, mat< 2, 2, T, Q > const &m2)
Definition type_mat2x2.inl:532
GLM_FUNC_DECL GLM_CONSTEXPR mat< 2, 2, T, Q > operator+(mat< 2, 2, T, Q > const &m)
Definition type_mat2x2.inl:349
Definition json.hpp:24659
Definition hash.inl:14
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:24734
namespace for Niels Lohmann
Definition json.hpp:5921
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:5945
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition json.hpp:5935
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:5925
Definition json.hpp:3622
typename BasicJsonType::object_t object_t
Definition json.hpp:3623
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3624
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3626
signed char char_type
Definition json.hpp:3669
static constexpr int_type eof() noexcept
Definition json.hpp:3683
uint64_t int_type
Definition json.hpp:3670
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3678
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3673
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3654
static constexpr int_type eof() noexcept
Definition json.hpp:3659
unsigned char char_type
Definition json.hpp:3645
uint64_t int_type
Definition json.hpp:3646
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3649
Definition json.hpp:3639
Definition json.hpp:3694
decltype(input_adapter(begin(std::declval< ContainerType >()), end(std::declval< ContainerType >()))) adapter_type
Definition json.hpp:6682
Definition json.hpp:285
std::false_type value_t
Definition json.hpp:286
Default type
Definition json.hpp:287
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:5638
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5613
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5603
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5625
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:5654
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5542
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5551
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5496
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5564
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5590
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5577
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:5673
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:5694
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:5683
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5518
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5529
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5509
Definition json.hpp:5490
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3576
Definition json.hpp:3561
Definition json.hpp:3617
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3591
Definition json.hpp:3586
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3606
Definition json.hpp:3601
Definition json.hpp:3157
T value_type
Definition json.hpp:3158
static constexpr std::size_t size() noexcept
Definition json.hpp:3159
an iterator value
Definition json.hpp:13037
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:13041
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:13043
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:13039
Definition json.hpp:3510
Definition json.hpp:3497
Definition json.hpp:4215
Definition json.hpp:4011
Definition json.hpp:3894
Definition json.hpp:3965
Definition json.hpp:3815
Definition json.hpp:3852
static constexpr auto value
Definition json.hpp:3853
Definition json.hpp:3968
Definition json.hpp:3981
Definition json.hpp:3788
Definition json.hpp:3938
Definition json.hpp:3848
Definition json.hpp:3859
ConstructibleStringType laundered_type
Definition json.hpp:3864
static constexpr auto value
Definition json.hpp:3867
Definition json.hpp:3984
Definition json.hpp:3726
Definition json.hpp:3707
Definition json.hpp:301
Definition json.hpp:3569
Definition json.hpp:3741
Definition json.hpp:3990
Definition json.hpp:3520
Definition json.hpp:4072
Definition json.hpp:4068
static one test(decltype(&C::capacity))
char one
Definition json.hpp:4069
static two test(...)
Definition json.hpp:3760
static constexpr bool value
Definition json.hpp:3774
Definition json.hpp:4001
Definition json.hpp:4237
std::random_access_iterator_tag iterator_category
Definition json.hpp:3337
Definition json.hpp:3325
Definition json.hpp:3306
Default base class of the basic_json class.
Definition json.hpp:13985
Definition json.hpp:256
void type
Definition json.hpp:257
Definition json.hpp:3701
Definition json.hpp:271
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
struct to capture the start position of the current token
Definition json.hpp:3070
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3074
std::size_t lines_read
the number of lines read
Definition json.hpp:3076
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3072
Definition json.hpp:3240
Definition json.hpp:3246
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3247
Definition json.hpp:5888
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:5890
Definition json.hpp:3177
Definition json.hpp:3196
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3198
static constexpr bool test(T val)
Definition json.hpp:4168
static constexpr bool test(T)
Definition json.hpp:4177
Definition json.hpp:4163
static constexpr bool test(T val)
Definition json.hpp:4122
static constexpr bool test(T val)
Definition json.hpp:4142
static constexpr bool test(T val)
Definition json.hpp:4132
static constexpr bool test(T val)
Definition json.hpp:4152
Definition json.hpp:4117
SAX interface.
Definition json.hpp:6816
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6817
typename BasicJsonType::string_t string_t
Definition json.hpp:6820
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6819
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6818
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6821
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19231
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:19234
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:19525
typename Container::value_type value_type
Definition json.hpp:19238
std::equal_to< Key > key_compare
Definition json.hpp:19242
iterator erase(iterator pos)
Definition json.hpp:19403
T mapped_type
Definition json.hpp:19233
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:19248
T & operator[](KeyType &&key)
Definition json.hpp:19290
typename Container::iterator iterator
Definition json.hpp:19235
const T & at(KeyType &&key) const
Definition json.hpp:19350
T & at(KeyType &&key)
Definition json.hpp:19322
const T & operator[](KeyType &&key) const
Definition json.hpp:19302
iterator find(const key_type &key)
Definition json.hpp:19487
iterator erase(iterator first, iterator last)
Definition json.hpp:19408
const T & at(const key_type &key) const
Definition json.hpp:19335
const_iterator find(const key_type &key) const
Definition json.hpp:19513
T & operator[](const key_type &key)
Definition json.hpp:19283
size_type erase(KeyType &&key)
Definition json.hpp:19384
typename Container::size_type size_type
Definition json.hpp:19237
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:19247
void insert(InputIt first, InputIt last)
Definition json.hpp:19548
size_type count(const key_type &key) const
Definition json.hpp:19461
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:19270
size_type erase(const key_type &key)
Definition json.hpp:19363
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:19252
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:19530
size_type count(KeyType &&key) const
Definition json.hpp:19475
Key key_type
Definition json.hpp:19232
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:19250
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:19545
const T & operator[](const key_type &key) const
Definition json.hpp:19295
iterator find(KeyType &&key)
Definition json.hpp:19501
T & at(const key_type &key)
Definition json.hpp:19307
typename Container::const_iterator const_iterator
Definition json.hpp:19236
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:19255
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:24703
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:24717